JDK源码学习记录---HashMap篇之如何理解tableSizeFor(int cap)

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

这段代码的作用就是找到第一个大于等于cap且是2的次幂的数,当然结果不会大于MAXIMUM_CAPACITY。

举个例子假设极限情况下cap为010000001

n=cap-1=010000000 除了最高位全是0,

n>>>1=00100000,

n|=n>>>1

01000000

00100000


01100000

后面一位就刷成1了,

继续n>>>2 = 00011000

n|=n>>>2

01100000

00011000


01111000

继续往后两位刷成1,加上第一步1位一共3位被刷成1

n|=n>>>4继续往后四位刷成1,到这步共7位刷成1,

n|=n>>>8继续往后刷8位,已经刷了15位了,

n|=n>>>16继续往后刷16位,到这步总共应该刷了31位,又因为n最大值不会超过1>>>30,也就是n最大不会超过30位,到这就可以确定全部刷1了,样例中的最后结果为01111111,最后在加上1,

结果为10000000就是2的n次方了。

注:上述二进制都省略了高位的0

为啥要n-1之后再计算,举个简单的例子假如n为01010101,最后得到到结果没问题10000000,但是如果n为100000,它原本就是2的次幂(2的5次幂),可以直接返回,但是经过上述一系列操作就变成1000000(2的6次幂)。

简单总结一下这n |= n >>> 1;
        n |= n >>> 2;
        n |= n >>> 4;
        n |= n >>> 8;
        n |= n >>> 16;

      n+=1,

这一系列的或,右移操作其实就是将原数二进制位中的0赋值为1,最后在加1就相当于原数除了最高位全部赋0,然后左移一位。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值