ConcurrentHashMap#tableSizeFor分析

ConcurrentHashMap中在创建时,会调用tableSizeFor方法进行计算尝试容量大小,这个方法原理就是通过巧妙的位运算,获取最接近入参的2的幂次方数。
简单思考,如果这个数本身不是2的幂次方,如何根据这样的数,计算最接近2的幂次方数呢?首先任意一个数,都可以表示为00...01XXX...XXX, 那么最接近它的2幂次方数肯定是最高位左移一位,低位全0,即:00...10000...000,那么如何得到这样的数呢?仔细观察发现,00...10000...000,其实就是00...01111...111+1得,所以问题就转为了如何求从最高位开始,低位全1的数,而这种数,我们可以通过位运算+或运算得到。

private static final int tableSizeFor(int c) { // 减一是针对入参c恰好是二的幂次方数 // 此时经移位后输出应该还是c本身 int n = c - 1; //通过移位加或运算,使n最终变成00...01111...111 // 移16位为止,是因为int型数据,总共32位,移动16刚好 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; }

【ConcurrentHashMap#tableSizeFor分析】举例:一个奇数
原始入参: 00...01XXX...XXX1
参数减一: 00...01XXX...XXX0
左移一位:00...001XX...XXX0
求或: 00...011XX...XXX0
左移二位: 00...00011X...XXX0
求或: 00...01111x...XXX0
...
发现规律没?每次移n位(n为2的幂次方),再与移位前的数求或,会使从高位开始的n位变成1,最终
移16位,正好变成: 00...011111...1111,此时原来的数,就变成了从高位开始全1的数,这个时候,获取最接近它的幂次方数就非常简单了,直接加1,
变成:00...011111...1111-->00...100000...0000

    推荐阅读