String 类的方法 -- hashCode()实现的常量系数
先上源码:
/**
* Returns a hash code for this string. The hash code for a
* {@code String} object is computed as
* <blockquote><pre>* s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
* </pre></blockquote> * using {@code int} arithmetic, where {@code s[i]} is the
* <i>i</i>th character of the string, {@code n} is the length of
* the string, and {@code ^} indicates exponentiation.
* (The hash value of the empty string is zero.)
*
* @return a hash code value for this object.
*/
public int hashCode() {
int h =hash;
if (h ==0 &&value.length >0) {
char val[] =value;
for (int i =0; i
h =31 * h + val[i];
}
hash = h;
}
return h;
}
相信很多朋友跟我一样,在查看String 类中hashCode() 方法具体实现的时候,会有个一疑问,为什么会有个常量系数 31,这个31是什么,怎么来的?有什么具体的含义;然后就各种查;
我也是简单的查了一下,网上的对这个解读的资料还是蛮多的,很轻松的找到可答案;
整理了一下,主要是有一下几种原因:
1、31是素数,素数是什么?素数也是质数,除了1和它本身以外,没有其他因数。所以不能被其他自然数整除
2、在存储数据计算hash地址的时候,我们希望相同的hash地址越少越好,也就是所谓的“冲突”,因为相同的hash地址的数据越多,生成的hash链表就越长,查找数据遍历的时间就越长,从而降低了查询效率。所以在选择系数的时候,我们希望这个系数越大越好(hash地址越大,冲突的概率越小,查询效率就高),但是相乘最好不要溢出(系数越大,越容易造成数据溢出,溢出的话,会造成数据的丢失)。而 31= 11111【二进制】,只占5bits。
3、我们都知道,计算机的乘法涉及到移位计算,一个数*2直接将这位数往左移一位即可,31*i = 2^5 * i - i, 相当于 i 向 左移动5位,再减 i,这样就转化成移位和减法结合的计算,比直接相乘的速度更快。也算是对算法的一种优化
综合以上几个原因,选择了31这个系数。