共计 869 个字符,预计需要花费 3 分钟才能阅读完成。
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;
}
举例:一个奇数
原始入参: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
正文完