代码浏览
话不多说 show me the code
/**
* Returns a power of two size for the given target capacity.
* 这个代码的作用是返回传入数的最小二次幂
*/
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;
}
看到这个源码的适合我内心是很抗拒的 ,但是也觉的很有意思这个代码,有一种代码之美
精简,整齐 对强迫症玩家及其友好,所以让我们来‘解刨一下’这段代码。
代码分析
首先呢,这段代码的第一行不用多说,只是对入参的int -1 。
但是在下面的多行频繁的用到了>>>
和 |=
这两个运算符 最后一行是一个 ? :
的三目运算符
,
位运算符介绍
运算符 | 操作 | 实例 | 介绍 |
---|---|---|---|
<< | 左移 | 2<<2 =8 即 10->1000 | 所有位向左移低位补0 |
>> | 右移 | 3>>1=1 即 3/2 =1 11->01 | 所有位向右移 正数补0 负数补1 |
>>> | 无符号右移 | 3>>1=1 -3>>>1=2147483646 | 所有位向右移首位补0 |
& | 与运算 | 6&3=2 | 两位与运算一方有0则为0 ,1&0=0 |
I | 或运算 | 6I3=7 | 两位与运算一方有1则为1 , 1I0=1 |
^ | 异或 | 6^3=5 | 110^10 =100 相同为0, 不相同为 1 |
~ | 反码 | ~6=-7 | 全部位取反 |
示例演示
public static void main(String[] args) {
System.out.println(tableSizeFor(200010));
System.out.println(tableSizeFor(100));
System.out.println(tableSizeFor(65));
System.out.println(tableSizeFor(20));
}
// 结果
// 262144
// 128
// 128
// 32
结果分析
结果就是输入数字的最小2的幂 就65来分析
static final int tableSizeFor(int cap) {
// cap = 65 = 1000001
int n = cap - 1; // n=1000000
n |= n >>> 1; // n = n|(n>>>1) = n|0100000 = 1000000|0100000= 1100000
n |= n >>> 2;// n = n|(n>>>2) = 1100000|0011000 = 1111000
n |= n >>> 4;// n = n|(n>>>4) = 1111000|0000111 = 1111111
n |= n >>> 8;// n = n|(n>>>8) = 1111111|0000000 = 1111111
n |= n >>> 16;// n = n|(n>>>16) 与上面同无变化 =1111111
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
// MAXIMUM_CAPACITY = 2^30 最后一句先判定后半部分 n>=MAXIMUM_CAPACITY 为 false 所以返回 n+1 = 10000000 n<0 为false 所以返回 n+1
//最终结果返回了 10000000 也就是 128
}
总结
在判定这些看似复杂的运算时 先弄清楚符号的含义 再进行数据的测试 对结果进行分析,相信你会更上一层楼,各位有觉的帮助到你的可以支持下,有哪里出错了也尽管指出,希望和大家共同进步。