取一个数的最近的2的幂值

该函数为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 。

猜你喜欢

转载自www.cnblogs.com/linghu-java/p/9389761.html
今日推荐