【转】 https://blog.csdn.net/fan2012huan/article/details/51097331
首先看下该方法的定义以及被使用的地方
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;
}
public HashMap(int initialCapacity, float loadFactor) {
// code...
this.threshold = tableSizeFor(initialCapacity);
}
tableSizeFor()这个方法的作用是找到大于等于给定容量的最小2的次幂值
>>>这个符号在java里是无符号右移的意思。
接下来分析一下这个方法的作用。
第一句
int n = cap - 1;
先不用考虑,我们分析完后面的之后再回过头来看它
然后是第二句
n |= n >>> 1;
我们这里假设n的初始值为9,那么9的二进制表示是
00000000 00000000 00000000 00001001
那么经历一次右移之后,二进制表示是
00000000 00000000 00000000 00000100
这两个值进行或运算之后,就是
00000000 00000000 00000000 00001101
这里我们如果看最高的1的话,那么可以发现右移1位并且或运算之后,使得最高位的右边一位也是1.
同理,我们可以下一句右移2位并且进行或运算之后,使得最高两位1的后两位也是1.
我们之后运行到最后一个右移,可以发现n的值变为了
00000000 00000000 00000000 00001111
当然该值大于1并且小于最大值那么+1之后,该值就变成了
00000000 00000000 00000000 00010000
惊讶的发现这个值不就是2的次幂嘛!!!
此时我们回到第一句-1,如果给定的n已经是2的次幂,但是不进行-1操作的话,那么得到的值就是大于给定值的最小2的次幂值。
至于为什么右移到16位,可以得到的最大值是32个1
11111111 11111111 11111111 11111111
这个是因为java的int类型用4个字节32位来进行存储的。最往后没有意义。