HashMap 容量為2次冪的原因
阿新 • • 發佈:2018-12-16
我們都知道 hashmap 的底層是一個數組加連結串列的結構,當向其中新增一個元素的時候,需要根據key的hash值,去確定其在陣列中的具體位置。
看原始碼,我們可以發現,確定陣列位置的實現是 i=(n-1)& hash
,其中 n 代表陣列的長度,即map的容量。
當n為2的冪次方時,(n-1)& hash 的值是均勻分佈的,我們假設n=16,hash從0開始遞增:
hash | (n-1)& hash | 結果 |
---|---|---|
0 | 1111 & 0 | 0 |
1 | 1111 & 1 | 1 |
2 | 1111 & 10 | 2 |
3 | 1111 & 11 | 3 |
4 | 1111 & 100 | 4 |
5 | 1111 & 101 | 5 |
…… | …… | …… |
16 | 1111 & 10000 | 0 |
17 | 1111 & 10001 | 1 |
18 | 1111 & 10010 | 2 |
當n不為2的冪次方時,(n-1)& hash 的值不是是均勻分佈的,我們假設n=15,hash從0開始遞增:
hash | (n-1)& hash | 結果 |
---|---|---|
0 | 1110 & 0 | 0 |
1 | 1110 & 1 | 0 |
2 | 1110 & 10 | 2 |
3 | 1110 & 11 | 2 |
4 | 1110 & 100 | 4 |
5 | 1110 & 101 | 4 |
…… | …… | …… |
16 | 1110 & 10000 | 0 |
17 | 1110 & 10001 | 0 |
18 | 1110 & 10010 | 2 |
由上面可以看出,當我們根據key的hash確定其在陣列的位置時,如果n為2的冪次方,可以保證資料的均勻插入,如果n不是2的冪次方,可能陣列的一些位置永遠不會插入資料,浪費陣列的空間,加大hash衝突。
另一方面,一般我們可能會想通過 % 求餘來確定位置,這樣也可以,只不過效能不如 & 運算。而且當n是2的冪次方時:hash & (length - 1) == hash % length
因此,HashMap 容量為2次冪的原因,就是為了資料的的均勻分佈,減少hash衝突,畢竟hash衝突越大,代表陣列中一個鏈的長度越大,這樣的話會降低hashmap的效能。