该函数为Hashmap和ConcurrentHashMap中的算法函数,
该算法充分使用了移位操作
1 /** 2 * Returns a power of two size for the given target capacity. 3 */ 4 static final int tableSizeFor(int cap) { 5 int n = cap - 1; 6 n |= n >>> 1; 7 n |= n >>> 2; 8 n |= n >>> 4; 9 n |= n >>> 8; 10 n |= n >>> 16; 11 return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1; 12 }
首先,为什么要对cap做减1操作。int n = cap - 1;
是为了防止,cap已经是2的幂。
如果cap已经是2的幂, 又没有执行这个减1操作,则执行完后面的几条无符号右移操作之后,
返回的capacity将是这个cap的2倍。
下面看看这几个无符号右移操作:
如果n这时为0了(经过了cap-1之后),则经过后面的几次无符号右移依然是0,最后返回的capacity是1(最后有个n+1的操作)。
这里只讨论n不等于0的情况。
第一次右移
n |= n >>> 1;
由于n不等于0,则n的二进制表示中总会有一bit为1,这时考虑最高位的1。通过无符号右移1位,则将最高位的1右移了1位,再做或操作,使得n的二进制表示中与最高位的1紧邻的右边一位也为1,如000011xxxxxx。
第二次右移
n |= n >>> 2;
注意,这个n已经经过了n |= n >>> 1;
操作。假设此时n为000011xxxxxx ,则n无符号右移两位,会将最高位两个连续的1右移两位,然后再与原来的n做或操作,这样n的二进制表示的高位中会有4个连续的1。如00001111xxxxxx 。
第三次右移
n |= n >>> 4;
这次把已经有的高位中的连续的4个1,右移4位,再做或操作,这样n的二进制表示的高位中会有8个连续的1。如00001111 1111xxxxxx 。
以此类推
注意,容量最大也就是32bit的正数,因此最后n |= n >>> 16;
,最多也就32个1,但是这时已经大于了MAXIMUM_CAPACITY
,所以取值到MAXIMUM_CAPACITY
。