Java中String的hashCode()方法背后的内容是什么?

我一直在调查java中的hashCode()方法,并发现String类的奇怪之处。 源代码如下:

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

代码本身非常简单。 但我想知道以这种方式计算哈希码的原因是什么?
为什么选择31?
为什么从0开始而不是value.length – 1?
是否保证这会使哈希码更不可能相互冲突?

是的,哈希码冲突的概率非常低,例如在String的情况下,它取决于字符串值。 如果我们没有使用new运算符创建任何String,那么如果新的String具有与已存在的值相同的值,则不会创建新的String对象,它引用堆中的旧值,在这种情况下,只有hashCode的值将与预期相同。

hashCode的一般契约是:

每当在执行Java应用程序期间多次在同一对象上调用它时,hashCode方法必须始终返回相同的整数,前提是不修改对象上的equals比较中使用的信息。 从应用程序的一次执行到同一应用程序的另一次执行,该整数不需要保持一致。

从Java 1.2开始,java.lang.String类在字符串的整个文本上使用乘积和算法实现其hashCode()。[2] 例如,给定java.lang.String类的实例,将具有由其定义的哈希码h(s)

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

其中术语使用Java 32位int加法求和,s [i]表示字符串的第i个字符,n是s的长度。

有关Apache Harmony的参考,方法hashCode是:

 public int hashCode() { if (hashCode == 0) { int hash = 0, multiplier = 1; for (int i = offset + count - 1; i >= offset; i--) { hash += value[i] * multiplier; int shifted = multiplier << 5; multiplier = shifted - multiplier; } hashCode = hash; } return hashCode; }