方法如下
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;
}
先说一下这个方法的作用:找到一个离cap最近的,大于cap的2的n次方数 ,如传入1,返回1;传入2,返回2;传入3,返回4
这个方法用了无符号右移操作(高位补0),涉及到二进制相关计算
首先要知道,2的整数次方的二进制特点,都是类似1(1),10(2),100(4),1000(8)…
结合这个方法的作用,给一个二进制数,如
00000000 00000000 00000000 10111101
那么离它最近的2的n次方数就是
00000000 00000000 00000001 00000000
如何才能得到这个数?可以通过00000000 00000000 00000000 11111111 + 1 得到(其实就是返回值中+1的原因)
那如何得到00000000 00000000 00000000 11111111 ? 这就是方法中右移和位或运算得到的
00000000 00000000 00000000 11111111
这个数其实就是
00000000 00000000 00000000 10111101
将最高位1后面的所有位都变为1
因为最高位有个1,只需要将其右移,再和原来的位或(有1即为1),就能达到最终都变为1
第一次右移1位(>>>1),可以将最高位1后面的1位变成1,到此有2个1
00000000 00000000 00000000 1
0111101
00000000 00000000 00000000 01
011110
00000000 00000000 00000000 11
011110
第二次右移2位(>>>2),可以将最高位2个1(第一次右移和或运算得到)后面的2位变成1,到此有4个1
00000000 00000000 00000000 11
011110
00000000 00000000 00000000 0011
0111
00000000 00000000 00000000 1111
0111
后面以此类推,因为java中int类型是32位的,所以5次右移(1,2,4,8,16)刚好能覆盖到32位数。
10000000 00000000 00000000 00000000
11000000 00000000 00000000 00000000(>>>1)
11110000 00000000 00000000 00000000(>>>2)
11111111 00000000 00000000 00000000(>>>4)
11111111 11111111 00000000 00000000(>>>8)
11111111 11111111 11111111 11111111(>>>16)