【问题标题】:Java - How can hashCode() function output small (or negative) number when string is bigJava - 当字符串很大时,hashCode() 函数如何输出小(或负)数
【发布时间】:2015-03-10 18:24:05
【问题描述】:

我创建了这个函数,当您输入简短的内容时,它的工作原理与原始 Java 函数相同,但如果我输入的内容大于 5-7 个字符 - 那么我会得到一些非常大的数字。 (而不是正确的哈希码)

这里是Java哈希函数的公式:

s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]

更简单的一种(仅适用于短字符串):

s = "abc" //String
n = 3 //Lenght of the String
s[0] = 'a'. ASCII code of 'a' = 97.
97 * (31 ^ (n - 1))
97 * (31 ^ (2))
97 * 961 = 93217

s[1] = 'b'. ASCII code of 'b' = 98.
98 * (31 ^ (n - 2))
98 * (31 ^ 1)
98 * 31 = 3038

s[2] = 'c'. ASCII code of 'c' = 99.
99 * (31 ^ (n - 3))
99 * (31 ^ 0)
99 * 1 = 99

93217 + 3038 + 99 = 96354 //

我想知道即使我输入一个巨大的字符串,Java 是如何使哈希变小的。

Java's hashcode of "Hello" - 69609650
My hashcode of "Hello" - 69609650


Java's hashcode of "Welcome to Tutorialspoint.com" - 1186874997
My hashcode of "Welcome to Tutorialspoint.com" - 5.17809991536626e+43

如果我们将数字相加,哈希怎么可能是负数?

【问题讨论】:

    标签: java string hash


    【解决方案1】:

    我怀疑你的实现(你没有显示)使用BigInteger 或类似的东西。 Java 只使用int - 所以当它溢出正 31 位整数的范围时,它会变成大的负整数,然后当你添加更多(正)值时,你会得到小的负整数,然后是小的正整数,然后是大的正整数 - 再回到大的负整数。

    【讨论】:

      【解决方案2】:

      String 的hashCode 只涉及int 的加法和乘法,所以它会导致int,它可能会溢出(因此是负值)。

      public int hashCode() {
          int h = hash;
          int len = count;
          if (h == 0 && len > 0) {
              int off = offset;
              char val[] = value;
              for (int i = 0; i < len; i++) {
                  h = 31*h + val[off++];
              }
              hash = h;
          }
          return h;
      }
      

      根据您的5.17809991536626e+43 值,您似乎正在执行浮点计算(也许您正在使用返回doubleMath.pow()),这对于大数会给出不同的结果。

      【讨论】:

        【解决方案3】:

        String$hashCode()的源代码:

         1494       public int hashCode() {
         1495           int h = hash;
         1496           if (h == 0 && count > 0) {
         1497               int off = offset;
         1498               char val[] = value;
         1499               int len = count;
         1500   
         1501               for (int i = 0; i < len; i++) {
         1502                   h = 31*h + val[off++];
         1503               }
         1504               hash = h;
         1505           }
         1506           return h;
         1507       }
        

        int 是一个 4 字节的有符号整数,它只会在哈希计算期间溢出,产生一个可以为负但始终受 int 约束的值。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-06-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-09-25
          • 1970-01-01
          相关资源
          最近更新 更多