H mod C = H & (C - 1) ?

在 Java 后端开发面试或源码阅读中,HashMap 永远是避不开的核心。很多人能熟练地背出它的扩容阈值、红黑树化条件,但当深入到源码底层,看到诸如 e.hash & (newCap - 1) 和 e.hash & oldCap 这样的位运算时,往往会陷入沉思。 一、 起源:为什么数组长度必须是 2 的次幂? 在散列表中,为了让数据均匀分布,最直观的想法是对哈希值进行取模(求余数): $$\text{索引位置} = \text{hash} \pmod{\text{Capacity}}$$然而,在 CPU 的底层底层执行中,除法和取模(%)是非常昂贵的算术操作(可能需要几十个时钟周期)。为了追求极致的性能,底层的数论定理为我们提供了一个完美的替代方案: 数学定理:当容量 $C$ 是 $2$ 的次幂($2^n$)时,对于任意整数 $H$,满足: $$H \pmod C \equiv H \ \& \ (C - 1)$$ 位运算(&)在 CPU 中只需要 1 个时钟周期!为了享受到这个性能红利,HashMap 在源码中将容量死死限制为 2 的次幂: // 默认初始容量 16 (2的4次方) static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; 裁剪器的魔术:hash & (newCap - 1) 以容量 16 为例,16 - 1 = 15(二进制:0000 1111)。任何 Hash 值与 15 进行 & 运算,高位都会被无情“抹零”,只有最后 4 位被保留下来: ...

2026-07-08 05:38:40 PM · 2 分钟