关于HashMap的table下标计算——tableSizeFor()方法解析

相关的代码片段如下:

代码段1:

    static final int MAXIMUM_CAPACITY = 1 << 30;
    /**
     * 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;
    }

代码段2:

public HashMap(int initialCapacity, float loadFactor) {
        /**省略此处代码**/
        this.loadFactor = loadFactor;
        this.threshold = tableSizeFor(initialCapacity);
    }

主要解析代码片段1:

1、tableSizeFor()的功用

    此方法用于找到大于等于initialCapacity的最小的2的幂(initialCapacity如果就是2的幂,则返回的还是这个数)

2、算数逻辑符解析

    1. >>>  表示:无符号右移

    举个例子:n=13,其二进制编码为00001101,

    n>>>1,前方补0,末位移除,最后得到00000110

    2. | 和 |=  表示:逻辑或 和 或等于

    举个例子:

        逻辑或|      1001|0110  结果是 1111 

        或等于|=   先逻辑或,结果再赋值给前面的变量 

                         n=5   (0101),  

                          n |=3,   3(0011)

                          n=6, 6(0110)

3、算法解析

int n = cap - 1;

    为什么要对cap做减1操作?

    这是为了防止,cap已经是2的幂。如果cap已经是2的幂, 又没有执行这个减1操作,则执行完后面的几条无符号右移操作之后,返回的capacity将是这个cap的2倍。

    如果n这时为0了(经过了cap-1之后),则经过后面的几次无符号右移依然是0,最后返回的capacity是1(最后有个n+1的操作)。 以下只讨论n不等于0的情况。 

第一次右移

n |= n >>> 1;

    由于n不等于0,则n的二进制表示中总会有一bit为1,这时考虑最高位的1。通过无符号右移1位,则将最高位的1右移了1位,再做或操作,使得n的二进制表示中与最高位的1紧邻的右边一位也为1,如000011xxxxxx。 

第二次右移

n |= n >>> 2;

    这个n已经经过了n |= n >>> 1; 操作。假设此时n为000011xxxxxx ,则n无符号右移两位,会将最高位两个连续的1右移两位,然后再与原来的n做或操作,这样n的二进制表示的高位中会有4个连续的1。如00001111xxxxxx 。

第三次右移

n |= n >>> 4;

    这次把已经有的高位中的连续的4个1,右移4位,再做或操作,这样n的二进制表示的高位中会有8个连续的1。如00001111 1111xxxxxx 。 

 以此类推 

   注意,容量最大也就是32bit的正数,因此最后n |= n >>> 16; ,最多也就32个1。但是这时已经大于了MAXIMUM_CAPACITY ,因为:

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

所以取值到MAXIMUM_CAPACITY 。  

 实例如下:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

看到这个地方,你应该基本明白了吧!

 

 

 

 

 

 

转载于:https://my.oschina.net/fl128818/blog/1555910

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值