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;
}
很简单,就是通过每个字节进行 s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1],那么为什么是31呢?
主要有以下几点:
- 31是优质质数,因为31 可以通过移位和减法来代替乘法,例如:31 * i == (i << 5)- i,现在的JVM可以主动完成优化代码。
- 31计算出来的hashcode值范围处于一个“适中”的区间,能够很好的降低哈希冲突,进行数据查找时可以提高效率。乘子太小容易导致计算出来的hashcode值区间太小,进行与运算时容易发生hash冲突。而乘子太大可能会导致相乘时造成数据溢出的概率增大,而 int的取值范围 -2^31 -- 2^31-1。 所以31比较合适。
- 31是一个奇素数,选择素数(质数)的好处就是如果我用一个数字来乘以这个素数,那么最终出来的结果也只能被素数本身和被乘数(以及被乘数的整除因子)还有1来整除!这样,以31作为乘子参与乘法计算得出的hashcode值,在后面进行取模(实际上是与运算时),得到相同index的概率会降低,即降低了哈希冲突的概率。
- 31只占用5bits(11111B),相乘造成数据溢出的概率较小。
这就是String的hashCode 源码实现及其为什么这样实现的原因了。