hashmap底层数组长度必须是2的幂,根本原因在于通过(n-1)&hash位运算实现高效、均匀的索引定位;若非2的幂,则位运算不等价于取模,导致哈希分布不均、扩容失效且性能下降。

HashMap底层数组长度必须是2的幂,根本原因在于它依赖 (n - 1) & hash 这个位运算来快速、均匀地定位元素存放位置。这不是硬性限制用户输入,而是底层自动保障的设计契约——你传10,它变16;传100,它变128。
位运算替代取模,速度更快
数组索引计算不用 hash % n(涉及除法,慢),而用 (n - 1) & hash(CPU级位操作,极快)。但这个等价关系只在 n 是 2 的幂时才成立:
- n = 16 → n−1 = 15 → 二进制 01111,与 hash 做 &,保留低 4 位,效果 ≡ hash % 16
- n = 15 → n−1 = 14 → 二进制 01110,第二位恒为 0,导致 hash 的第 1 位被屏蔽,结果失真
保证所有桶都有机会被使用
当 n−1 的二进制含 0(如 n=10 → n−1=9 → 1001),某些位永远不参与运算:
- hash 的第 1 位和第 3 位(从 0 开始)无论 0 或 1,都不影响结果
- 索引 2、4、5、6、7 等可能长期空置,实际可用桶数远少于容量
- 大量不同 hash 被压到少数几个桶,链表变长,查询退化为 O(n)
扩容时无需重新哈希
扩容翻倍(如 16→32)后,新掩码比旧掩码多一位。此时每个节点只需看 hash 在“新增最高位”是否为 1:
- 为 0 → 留在原索引
- 为 1 → 移到 原索引 + 旧容量
- 判断仅需
(e.hash & oldCap) == 0,一次位运算搞定
若容量不是 2 的幂,这个高位迁移逻辑失效,必须对每个 key 重算 hash 和新索引,性能断崖式下降。
初始化时已自动对齐
你调用 new HashMap(10),内部会走 tableSizeFor(10) 方法,通过无符号右移 + 按位或,快速得到 16。整个过程不依赖用户经验,也不抛异常,而是静默兜底,确保底层始终满足 2 的幂约束。











