個人理解 做下記錄,不正確的地方望不吝賜教
這是hashmap初始化容量時候 對容量大小做的處理,保證初始化容量為最近的2的冪次方(JDK1.8)
static final int tableSizeFor(int cap) {
int n = cap - 1;
n |= n >>> 1;
n |= n >>> 2;
n |= n >>> 4;
n |= n >>> 8;
n |= n >>> 16;
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}
思考,為啥非得是2的冪次方 ,2的倍數不行么,奇數不行么?
結合源碼加別人的資料,做如下解釋:
1.奇數不行的解釋很能被接受,在計算hash的時候,確定落在數組的位置的時候,計算方法是(n - 1) & hash ,奇數n-1為偶數,偶數2進制的結尾都是0,經過&運算末尾都是0,會
增加hash沖突。
2.為啥要是2的冪,不能是2的倍數么,比如6,10?
2.1 hashmap 結構是數組,每個數組里面的結構是node(鏈表或紅黑樹),正常情況下,如果你想放數據到不同的位置,肯定會想到取余數確定放在那個數據里, 計算公式:
hash % n,這個是十進制計算。在計算機中, (n - 1) & hash,當n為2次冪時,會滿足一個公式:(n - 1) & hash = hash % n,計算更加高效。
2.2 只有是2的冪數的數字經過n-1之后,二進制肯定是 ...11111111 這樣的格式,這種格式計算的位置的時候,完全是由產生的hash值類決定,而不受n-1 影響。你可能會想,
受影響不是更好么,又計算了一下 ,hash沖突可能更低了,這里要考慮到擴容了,2的冪次方*2,在二進制中比如4和8,代表2的2次方和3次方,他們的2進制結構相 似,比如
4和8 00000100 0000 1000 只是高位向前移了一位,這樣擴容的時候,只需要判斷高位hash,移動到之前位置的倍數就可以了,免去了重新計算位置的運算。