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