n |= n >>> 1 HashMap的tableSizeFor方法中理解过程

该代码段是HashMap中用于计算最接近输入值(cap)的2的次方数的方法。它通过右移运算和按位或操作,确保结果是2的幂,对于非2的幂的输入,最终结果会加1,如输入10,返回16。这个过程保证了哈希表的容量始终是2的幂,优化了性能。
摘要由CSDN通过智能技术生成

在HashMap的tableSizeFor方法中这段代码很有意思

    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;
    }

首先需要知道这个代码是干嘛的
他的意义就是找到比输入大的,并且与输入相邻的2的次方数。

比如输入3,输出4。输入5、6、7,输出8。

然后,什么是|

就是二进制运算时,有1就是1。
1|0=1,1|1=1,0|0=0。

右移几位。直接往右移就完了,0补位,很简单。
111>>>1=011。
111>>>2=001。

右移几位。直接往右移就完了,0补位,很简单。
111>>>1=011。
111>>>2=001。

	    n |= n >>> 1;
        n |= n >>> 2;
        n |= n >>> 4;
        n |= n >>> 8;
        n |= n >>> 16;

下面开始计算。以输入10为例。你也可以随便选择一个数,按照下面步骤进行。

比如输入10,10-1=9,9化成二进制就是:1001。
然后开始这步:

n |= n >>> 1;

此时n=1001,n先右移1位,变成0100。
然后0100再与之前的n做或运算,也就是0100|1001=1101。
此时n=1101。

然后是:

n |= n >>> 2;

1101>>>2=0011
0011|1101=1111
此时n=1111。

然后是:

 n |= n >>> 4;

聪明的人已经知道了,以后的结果都是1111,不信给你算。

1111>>>4=0000
0000|1111=1111
此时n=1111。

然后是

 n |= n >>> 8;

1111>>>8=0000 0000
0000 0000|1111也就是0000 0000|0000 1111 = 0000 1111
0000 1111也就是1111。
此时n=1111。

移16就不用算了,你得多笨。

这时候发现了啊,一直右移,做或运算,最后就变成了全是1的。然后再看tableSizeFor的代码最后一行,最后要得到n+1。

return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;

这段代码先是判断n是否小于0,这个防御判断就不用管了。大于0的时候,判断n和MAXIMUM_CAPACITY的大小,取值MAXIMUM_CAPACITY或者n+1。

这里可以这么理解:
n >= MAXIMUM_CAPACITY 可以写成n + 1 > MAXIMUM_CAPACITY
也就是:
(n + 1 > MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
然后就理解成,n+1和MAXIMUM_CAPACITY谁大就取谁。

我们输入的10,最后得出1111,1111+1之后是几?是10000,16,也就是2的4次方。

也就是处理完之后,必然是全1,也就是2的幂-1,那么返回n+1;

int n = cap - 1;

这一步是为了防止传入的cap本来就是2的幂,结果处理成2n+1了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值