1、減少哈希碰撞
核心原因:HashMap的所有設計都依賴于數組長度為2的冪次方這一前提。
- 索引計算使用 (n-1)&hash ,其中 n 是數組長度
- 當 n 是 2 的冪次方時,n-1 的二進制形式是全 1(例如,15——>1111)
- 這使得哈希分布更均勻,減少哈希碰撞概率
- 擴容為 2 倍能保證新容量仍然是 2 的冪次方
原始容量16: n-1=15 (1111)
擴容后32: n-1=31 (11111)
2、優化元素遷移效率(JDK1.8改進)
- 元素的新位置只有兩種可能:
- 保持原位置不變
- 原位置 + 原容量
為什么呢?
新索引 = e.hash & (newCap - 1)
由于newCap = oldCap << 1,newCap - 1 比 oldCap - 1 多一個高位1
所有只需要看 e.hash 新增的高位是0還是1:
0則索引不變
1則索引? = 原索引 + oldCap
實現優勢:
- 無序重新計算hash值
- 只需一次位判斷即可確定新位置
- 遷移時間復雜度從 O(n) 減低到 O(1)
元素hash值: ... 0001 1101 (低4位1101=13)
oldCap=16(10000), newCap=32(100000)
判斷第5位(從右數第5位):
如果是0: 新位置仍然是13
如果是1: 新位置是13+16=29