What's behind the hashCode() method for String in Java?
本问题已经有最佳答案,请猛点这里访问。
我一直在研究爪哇的EDCOX1 0方法,找到了一个字符串类奇怪的。源代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 | 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?有没有保证这会减少哈希代码之间的冲突?
是的,哈希代码冲突的概率非常低,例如,对于字符串,它取决于字符串值。如果不使用new运算符创建任何字符串,那么如果新字符串的值与已经存在的值相同,则不会创建新的字符串对象,它引用堆中的旧值,在这种情况下,只有hashcode的值与预期值相同。
hashcode的总合同是:
每当Java应用程序执行过程中在同一对象上多次调用时,HASCODE方法必须始终返回相同的整数,如果没有修改对象中的相等信息。从应用程序的一次执行到同一应用程序的另一次执行,这个整数不需要保持一致。
从Java 1.2,JavaLang.String类使用一个乘积和算法实现整个字符串中的HASCODE()。[2 ]给定一个JavaLang.String类的实例S,将有一个哈希代码H(s)定义。
1 | h(s)=s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] |
在使用Java32位int加法求和的条件下,s[i]表示字符串的第i个字符,n是s的长度。
对于Apache Harmony中的参考,方法hashcode是:
1 2 3 4 5 6 7 8 9 10 11 12 | 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; } |
号