我一直在研究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?
有保证这样做可以使哈希码更不可能发生冲突吗?
hash
直接进行操作,那么它就不是线程安全的,因为一个线程可能在另一个线程仍在计算哈希值时尝试读取hash
。在这种情况下,hash != 0
,所以hashCode
会返回中间值,这是不正确的。如果你只在最后一次使用正确的值修改hash
(就像Oracle的实现一样),那么hash
的值始终是0
或者正确的哈希值(因为访问int
是原子操作)。 - undefined