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;
}
若是String value="abcd"; 那麼其計算結果爲:
value[0]=a;
h=31*0+a; --31*0+97
=a; --97
value[1]=b;
h=31*(31*0+a)+b; --31*97+98
=31*a+b; --3007+98=3105
value[2]=31*(31*a+b)+c; --96255+99
=31*31*a+31*b+c; --96354
value[3]=31*(31*31*a+31*b+c)+d --31*96354+100
=31*31*31*a+31*31*b+31*c+d --2986974+100
h=31^(n-1)*value[0]+31^(n-2)*value[1]+31^(n-3)*value[2]+value[n-1];
進制轉換的表示方法爲:16進制的20表示成10進制就是:2×16¹+0×16º=32
那麼HashCode的計算方式就是字符的ascii碼 按照31進制的計算方式去計算。
-------------------------------------------------------------------------------------------
你們都知道,計算機的乘法涉及到移位計算。當一個數乘以2時,就直接拿該數左移一位便可!選擇31緣由是由於31是一個素數!java
所謂素數:優化
質數又稱素數。指在一個大於1的天然數中,除了1和此整數自身外,無法被其餘天然數整除的數。spa
在存儲數據計算hash地址的時候,咱們但願儘可能減小有一樣的hash地址,所謂「衝突」。若是使用相同hash地址的數據過多,那麼這些數據所組成的hash鏈就更長,從而下降了查詢效率!因此在選擇係數的時候要選擇儘可能長(31 = 11111[2])的係數而且讓乘法儘可能不要溢出(若是選擇大於11111的數,很容易溢出)的係數,由於若是計算出來的hash地址越大,所謂的「衝突」就越少,查找起來效率也會提升。ci
31能夠 由i*31== (i<<5)-1來表示,如今不少虛擬機裏面都有作相關優化,使用31的緣由多是爲了更好的分配hash地址,而且31只佔用5bits!源碼
在java乘法中若是數字相乘過大會致使溢出的問題,從而致使數據的丟失.虛擬機
而31則是素數(質數)並且不是很長的數字,最終它被選擇爲相乘的係數的緣由不過與此!hash
如i*31==(i<<5)-1 用二進制表示就是:
1<<5 移位 位100000
11111==100000-1