tableSizeFor 返回不小于 cap 的最小 2 的幂;通过 cap−1 后多次无符号右移并或运算,将最高位后所有位设为 1,再加 1 实现,且 cap 为 2 的幂时减 1 可避免结果翻倍。

tableSizeFor 的作用是:给定一个正整数 cap,返回不小于 cap 的最小 2 的幂。例如输入 10,返回 16;输入 16,返回 16;输入 17,返回 32。
核心思路:把最高位之后所有位都变成 1,再加 1
因为 2 的幂的二进制形式是 1 后面全 0(如 8→1000,16→10000),所以“不小于 cap 的最小 2 的幂”等价于:把 cap 的最高有效位(MSB)左边补 1,右边全填 1,再加 1。实际通过位运算快速“抹平”低位来逼近。
具体步骤(以 int 为例)
源码中 tableSizeFor 实现如下:
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;
}关键在于这 5 次右移与或操作。以 cap = 10 为例说明:
立即学习“Java免费学习笔记(深入)”;
- cap − 1 = 9 → 二进制 1001
- n |= n >>> 1 → 1001 | 0100 = 1101
- n |= n >>> 2 → 1101 | 0011 = 1111
- 后续 >>>4、>>>8、>>>16 对 4 位数已无影响,结果仍是 1111
- n + 1 = 1111 + 1 = 10000 = 16
每次右移并或操作,都在把高位的 1 “扩散”到更低的连续位置。最多 5 步(因 int 是 32 位,2⁵=32),就能确保从最高位开始,所有低位全为 1。
为什么先减 1?
防止 cap 本身就是 2 的幂时结果翻倍。例如 cap = 16(10000):
- 若不减 1:10000 经扩散变 11111,+1 得 100000 = 32 ❌
- 减 1 后:15(01111)→ 扩散仍为 01111 → +1 = 10000 = 16 ✅
所以 cap−1 是关键预处理,使 2 的幂输入也能得到自身。
边界情况处理
源码末尾有两处保护:
n :cap ≤ 1 时,cap−1 ≤ 0,右移或后可能为负(符号位扩展),此时直接返回 1-
n >= MAXIMUM_CAPACITY(默认 1
这些保证了方法对任意 int 输入都安全、正确。


















