关于java:为什么选择31在hashcode()实现中进行乘法运算?

Why chose 31 to do the multiplication in the hashcode() implementation ?

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
Why does Java's hashCode() in String use 31 as a multiplier?
Why use a prime number in hashCode?

从有效的Java项目9:在重写相等时总是重写哈希代码,请考虑下面的相关代码片段,该代码片段重写对象类中定义的HASCODE()。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public final class PhoneNumber {
  private final short areaCode;
  private final short prefix;
  private final short lineNumber;
  ......//Rest ignored on purpose
  .....

private volatile int hashCode; // (See Item 71)
@Override public int hashCode() {
   int result = hashCode;
   if (result == 0) {
    result = 17;
    result = 31 * result + areaCode;
    result = 31 * result + prefix;
    result = 31 * result + lineNumber;
    hashCode = result;
   }
 return result;
 }
}

我理解为什么选择非零初始值"17"。我还理解乘法是在每一步中进行的,这样字段的顺序在计算hashcode()时就起到了重要的作用。但我不明白为什么选择31作为乘法的值。有人能给我解释一下为什么吗?这是布洛赫关于31的话,但我不太明白。我特别不明白下面的斜体字。

The value 31 was chosen because it is an odd prime. If it were even and the multiplication overflowed, information would be lost, as multiplication by 2 is equivalent to shifting. The advantage of using a prime is less clear, but it is traditional.


向左移位只会在右边引入一个零,在数字的二进制表示的左边会丢失一点,所以这是一个明显的信息丢失。重复这个过程会逐渐丢失从早期计算中积累的所有信息。这意味着输入哈希代码计算的字段越多,对早期字段的最终结果的影响就越小。


他使用素数的原因是它更可能产生随机模式。例如,如果你用9,你可以得到3的倍数。

afaik 31用于字符串,因为字母表中少于31个字母,这意味着最多6个字母的所有单词都具有唯一的哈希代码。例如,如果使用61(素数小于64),最多5个字母将产生唯一的代码;如果使用13(素数小于16),则可能与两个字母的单词发生冲突。


我将描述一个不同数字的答案,但我怀疑推理是相似的。对字符x的散列值的贡献是x*b^k,在这种情况下,b是31,k取决于x在字符串中的位置及其长度。这种算法通常是按字的大小进行模运算的。因此,我们希望b^k对于k的不同值是不同的。

现在,在Gonnet和Baeza Yates的"算法和数据结构手册"第3.3.1节"实际散列函数"中,他们说"对于这个函数,建议值b=131,因为b^i的最大循环mod 2^k为8<=k<=64。"我想知道哪个循环长度31的mod 2^32?我相信31将适合SPARC立即操作数,但131不适合。