String 类的方法 -- hashCode()实现的常量系数

2018-10-17  本文已影响0人  Janice_x

先上源码:

/**

* 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这个系数。

上一篇下一篇

猜你喜欢

热点阅读