tableSizeFor方法
2019-01-12 本文已影响0人
犄角芝士
/**
* 根据容量参数,返回一个2的n次幂的table长度。
*/
private static final int tableSizeFor(int c) {
int n = c - 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;
}
先看一下tableSizeFor()的输入与输出
public static void main(String[] args) {
System.out.println(tableSizeFor(1));
System.out.println(tableSizeFor(5));
System.out.println(tableSizeFor(25));
System.out.println(tableSizeFor(125));
System.out.println(tableSizeFor(625));
}
输出:
1
8
32
128
1024
通过输出可以大致猜到tableSizeFor的作用是返回一个大于输入参数且最小的为2的n次幂的数。
我们再来看看是怎么做到的。
当输入为25的时候,n等于24,转成二进制为1100,右移1位为0110,将1100与0110进行或("|")操作,得到1110。接下来右移两位得11,再进行或操作得1111,接下来操作n的值就不会变化了。最后返回的时候,返回n+1,也就是10000,十进制为32。按照这种逻辑得到2的n次幂的数。
再来看一个例子,当n=1<<30的时候:
01 00000 00000 00000 00000 00000 00000 (n)
01 10000 00000 00000 00000 00000 00000 (n |= n >>> 1)
01 11100 00000 00000 00000 00000 00000 (n |= n >>> 2)
01 11111 11000 00000 00000 00000 00000 (n |= n >>> 4)
01 11111 11111 11111 00000 00000 00000 (n |= n >>> 8)
01 11111 11111 11111 11111 11111 11111 (n |= n >>> 16)
由于int类型为32位,所有即使除符号为之外只有第一位为1的情况,也能将所有的位全部变成1,不过由于最后计算出来为int类型的最大值,此时返回n+1会导致溢出,不能返回期望的结果,这也是为什么在方法开始是要执行int n = c - 1;
的原因。
那么又有一个问题,为什么要在前面减1,然后在后面加回来呢?当输入为0的时候就会发现,方法的输出为1,HashMap的容量只有大于0时才有意义。