HashMap初始化大小时的巧妙位运算
我们知道HashMap会保证其大小等于2的幂次方,也就是二进制只有一位为1,因为这可以使得它进行求余运算的时候可以使用&(length-1),扩容resize的时候还可以使用&oldLength,这些位运算可以加快map的插入和扩容速度
那么如果我们在实例化对象的时候设置它的大小,它会怎么求呢?
本来我并没有留意的,但是有一次做题,它说使用位运算求一个>=n的2次幂,让我想起了HashMap,然后看了一下源码,vocal,二进制太巧妙了吧
我们可以根据代码猜出作者的思路
首先求一个>=n的最小2的幂,有两种情况:
- 2^m>n
- 2^m=n
我们先考虑第一种情况,2^m肯定在n最高位1的前一位(第m+1位),
如果第1->m位全是1,那么加1就可以得到2^m,
我们如果使得n进行位运算之后变成m+1位后全1,我们无需考虑其他位置上的值,因为我们知道第m位是1,保证能通过第m位1能得出全1就行,根据代码第一步位运算n=n|n>>>1,使得前两位都是1,第二步前四位,以此类推,因为int就32位,所以只需要运算到>>>16,结果就是2^m-1,加1之后得到 2^m
如果是第二种情况呢?本来就是2^m的话直接按上一种情况操作结果会变成 2^(m+1),所以我们要先减1,让第一位1后移一位,减1对第一种情况没有影响,所以就得出了上面的结果
因为使用的是二进制,所以关于2的运算都可以使用位运算变得很巧妙