Integer 的 Integer.highestOneBit方法源码解读

今天在学习JDK7 HashMap源码时,它在创建数组容量大小的时候用到了Integer.highestOneBit方法

   HashMap中的源码

    private static int roundUpToPowerOf2(int number) {
        // assert number >= 0 : "number must be non-negative";
        return number >= MAXIMUM_CAPACITY
                ? MAXIMUM_CAPACITY
                : (number > 1) ? Integer.highestOneBit((number - 1) << 1) : 1;
    }

  Integer中的 highestOnBit方法源码

 public static int highestOneBit(int i) {
        // HD, Figure 3-1
        i |= (i >>  1);
        i |= (i >>  2);
        i |= (i >>  4);
        i |= (i >>  8);
        i |= (i >> 16);
        return i - (i >>> 1);
    }

刚看到这个代码,我直接黑人问号!后来老师和网上资料的学习有了一点眉目。

JDK注释

* Returns an {@code int} value with at most a single one-bit, in the
* position of the highest-order ("leftmost") one-bit in the specified
* {@code int} value.  Returns zero if the specified value has no
* one-bits in its two's complement binary representation, that is, if it
* is equal to zero.
*
* @return an {@code int} value with a single one-bit, in the position
*     of the highest-order one-bit in the specified value, or zero if
*     the specified value is itself equal to zero.
* @since 1.5

额,再次黑人问号,用翻译插件翻译文本如下

返回具有至多单个 1 位的 int 值,在指定的 int 值中最高位(最左边)的 1 位的位置。如果指定的值在其二进制补码表示形式中不具有 1 位,即它等于零,则返回零。

在用通俗易懂的话来说就是:

  • 如果一个数是0, 则返回0;
  • 如果是负数, 则返回 -2147483648:【1000,0000,0000,0000,0000,0000,0000,0000】(二进制表示的数);
  • 如果是正数, 返回的小于等于这个数的2的N次方

 例如:举几个例子

public static void main(String[] args) {
   System.out.println(Integer.highestOneBit(0));   // 0
   System.out.println(Integer.highestOneBit(16));  //16
   System.out.println(Integer.highestOneBit(15));  //8
   System.out.println(Integer.highestOneBit(-1));  //-2147483648  = Integer.MIN_VALUE
}

 

按照代码的逻辑思路,我们一步一步来解读解读,例如数字 17

int 占 4个字节,32位, 17的二进制数为: 0000 0000 0000 0000 0000 0000 0001 0001,因为前面都是重复的 0 我们只用 后八位来做演示  0001 0001

17     0001 0001
>>1    0000 1000
|      0001 1001
>>2    0000 0110
|      0001 1111
>>4    0000 0001
|      0001 1111
>>8    0000 0000
|      0001 1111
>>16   0000 0000
|      0001 1111

//i - (i >> 1)
       0001 1111
       0000 1111
     = 0001 0000   // 16 的二进制位

看到这里可能看出来点门道,我们则可以测试把最高位以后的位都用星号表示

17     0001 ****
>>1    0000 1***
|      0001 1***
>>2    0000 011*
|      0001 111*
>>4    0000 0001
|      0001 1111
>>8    0000 0000
|      0001 1111
>>16   0000 0000
|      0001 1111

//i - (i >> 1)
       0001 1111
       0000 1111
     = 0001 0000   // 16 的二进制位

这个运算的过程无非就是将该数字对应的二进制数中除最高位的1之外的其他bit位都清零,则拿到了我们想要的结果。

右移与或运算的目的就是想让某个数字的低位都变为1,再用该结果 减去 该结果右移一位后的结果,则相当于清零了原数字的低位。即得到了我们想要的结果。

 

补充:1、为什么是右移 1 2 4 8 16 而不是其他的数呢?

 1 + 2 + 4 + 8 + 16 = 31,  2的31次方,直到把原来最高位变成0所以要这么多次

 

补充:1、为什么是在HashMap源码调用时要先-1?

例如:如果数字为16,不 -1,在运算后得到的还会是16,计算出的opacity = 32 ;违背了hash容量计算——大于等于该数的2次方幂。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值