HashMap底层中tableSizeFor(int i)方法作用是确保底层数组扩容时新的数组容量为2的幂次数,即2n。
jdk1.8:
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;
}
(注意:n是从0开始计数)
我们知道2n表示为二进制时除去最高位第n位为1外,最高位后的位均为0,例如,8 => 1000。所以当一个数小于2n大于2n-1时,它的n-1位就是它的最高位,例如,6 => 110。
此外,我们知道2n-1其所有二进制位均为1,例如,7 => 8-1 => 0111。
因此我们的目标就是求得这个位数均为1的二进制数。
tableSizeFor(int i)方法是通过向右移位并通过或运算来不断的替换最高位后的1,每次运算一次后1的个数就会翻倍,因此移位的数字依次为1,2,4,8,16。
jdk11:
static final int tableSizeFor(int cap) {
int n = -1 >>> Integer.numberOfLeadingZeros(cap - 1);
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}
public static int numberOfLeadingZeros(int i) {
// HD, Count leading 0's
if (i <= 0)
return i == 0 ? 32 : 0;
int n = 31;
if (i >= 1 << 16) { n -= 16; i >>>= 16; }
if (i >= 1 << 8) { n -= 8; i >>>= 8; }
if (i >= 1 << 4) { n -= 4; i >>>= 4; }
if (i >= 1 << 2) { n -= 2; i >>>= 2; }
return n - (i >>> 1);
}
首先观察tableSizeFor方法,我们发现返回语句并没有发生变化,这说明我们依旧是要求一个全为1的二进制串。
此外,-1在计算机中的二进制表示形式为1111 1111 1111 1111 1111 1111 1111 1111
,全部为1。结合int n = -1 >>> Integer.numberOfLeadingZeros(cap - 1);
语句得知我们需要cap - 1的二进制位数,然后用总位数减去二进制串的位数就是最后-1需要向右移动的位数。
注意:n是从0开始计数的。
接下来我们需要通过numberOfLeadingZeros
方法来获取这个需要移动的位数。在该方法中通过位移来判断输入的数的位数。int n = 31
是因为int类型的数是32位的,然后
与216比较判断是否超过16位,超过则进行移位减小并减小n的值
与28比较上一步余下的位数是否超过8位,超过则进行移位并减小n的值
与24比较上一步余下的位数是否超过4位,超过则进行移位并减小n的值
与22比较上一步余下的位数是否超过2位,超过则进行移位并减小n的值
最后n >>> 1
确保余下的位数不超过1位,此时i
的位数已经随着n
的不断减小而减去,剩下的位数便是最后需要移位的位数,返回即可。
通过numberOfLeadingZeros方法得到移位位数后进行移位并加1得到最后的结果。
附录:
移位数 | 移动后的二进制串 | +1 |
---|---|---|
0 | 11111111111111111111111111111111 | 0 |
1 | 1111111111111111111111111111111 | -2147483648 |
2 | 111111111111111111111111111111 | 1073741824 |
3 | 11111111111111111111111111111 | 536870912 |
4 | 1111111111111111111111111111 | 268435456 |
5 | 111111111111111111111111111 | 134217728 |
6 | 11111111111111111111111111 | 67108864 |
7 | 1111111111111111111111111 | 33554432 |
8 | 111111111111111111111111 | 16777216 |
9 | 11111111111111111111111 | 8388608 |
10 | 1111111111111111111111 | 4194304 |
11 | 111111111111111111111 | 2097152 |
12 | 11111111111111111111 | 1048576 |
13 | 1111111111111111111 | 524288 |
14 | 111111111111111111 | 262144 |
15 | 11111111111111111 | 131072 |
16 | 1111111111111111 | 65536 |
17 | 111111111111111 | 32768 |
18 | 11111111111111 | 16384 |
19 | 1111111111111 | 8192 |
20 | 111111111111 | 4096 |
21 | 11111111111 | 2048 |
22 | 1111111111 | 1024 |
23 | 111111111 | 512 |
24 | 11111111 | 256 |
25 | 1111111 | 128 |
26 | 111111 | 64 |
27 | 11111 | 32 |
28 | 1111 | 16 |
29 | 111 | 8 |
30 | 11 | 4 |
31 | 1 | 2 |
END