先上源碼:
/**
* 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() 方法具體實現(xiàn)的時候荤崇,會有個一疑問该押,為什么會有個常量系數(shù) 31,這個31是什么向图,怎么來的?有什么具體的含義祥楣;然后就各種查类垫;
我也是簡單的查了一下,網(wǎng)上的對這個解讀的資料還是蠻多的此衅,很輕松的找到可答案强戴;
整理了一下亭螟,主要是有一下幾種原因:
1、31是素數(shù)骑歹,素數(shù)是什么预烙?素數(shù)也是質(zhì)數(shù),除了1和它本身以外道媚,沒有其他因數(shù)扁掸。所以不能被其他自然數(shù)整除
2、在存儲數(shù)據(jù)計算hash地址的時候最域,我們希望相同的hash地址越少越好谴分,也就是所謂的“沖突”,因為相同的hash地址的數(shù)據(jù)越多镀脂,生成的hash鏈表就越長狸剃,查找數(shù)據(jù)遍歷的時間就越長,從而降低了查詢效率狗热。所以在選擇系數(shù)的時候钞馁,我們希望這個系數(shù)越大越好(hash地址越大,沖突的概率越小匿刮,查詢效率就高)僧凰,但是相乘最好不要溢出(系數(shù)越大,越容易造成數(shù)據(jù)溢出熟丸,溢出的話训措,會造成數(shù)據(jù)的丟失)。而 31= 11111【二進(jìn)制】光羞,只占5bits绩鸣。
3、我們都知道纱兑,計算機(jī)的乘法涉及到移位計算呀闻,一個數(shù)*2直接將這位數(shù)往左移一位即可,31*i = 2^5 * i - i, 相當(dāng)于 i 向 左移動5位潜慎,再減 i捡多,這樣就轉(zhuǎn)化成移位和減法結(jié)合的計算,比直接相乘的速度更快铐炫。也算是對算法的一種優(yōu)化
綜合以上幾個原因垒手,選擇了31這個系數(shù)。