HashMap的tableSizeFor方法源码分析(jdk1.8)

声明:以下对源码解读,是本人个人理解,水平有限,如有错误,请及时告诉我!

在创建HashMap对象,并在构造器传入初始化容量的时候,会调用tableSizeFor方法,返回 >=初始化对象最近的2的倍数。

阅读前需要了解的知识(以下为快速理解,如需详情百度)
如果已了解位移位运算,请跳过

>>>(无符号右移):整体二进制数字向右移动,移动后,高位补0,末尾舍去 例:55(二进制110111) >>> 1 = 27(二进制11011)
55(二进制110111) >>> 2 = 13(二进制1101)
>>> 后面的数字代表位移几位

|(按位或运算):两个数字的二进制做运算,两边的每一位数字做 | 运算,有1则为1(同类似条件或 | 运算,有true则为true)一个道理,把二进制0看作false,1作ture,进行按位或运算,得到一个新数字(我估计我可能文字说不明白,看例子)。
0 | 0 = 0, 0 | 1 = 1, 1 | 0 = 1, 1 | 1 = 1 【把0当作false,1当作true,好记,好理解】
例子:110111(十进制55)| 11011(十进制27)
在这里插入图片描述

11011(十进制27) 我的图是 011011,高位补0

2的倍数在二进制当中,都是1000…后面全是0。
2(10)4(100)8(1000)16(10000)
那么得到一个数,>=他的2的倍数,只有这个数的二进制全变为 111…然后+1即可
1(1)3(11)7(111)15(1111)
上面的数字 +1 即变为了2的倍数
源码

    /**
     * Returns a power of two size for the given target capacity.
     */
     //                       传入的初始化容量
    static final int tableSizeFor(int cap) {
    	//初始化容量 - 1。保证cap本身是2的倍数,返回也是cap。
    	//例如:cap = 32 ,返回 32。如没有-1,cap = 32 返回 64
        int n = cap - 1;
        //按位或,无符号右移 n = n | (n >>> 1,2,4,8,16)
        n |= n >>> 1;
        n |= n >>> 2;
        n |= n >>> 4;
        n |= n >>> 8;
        n |= n >>> 16;
        // 到这里n的二进制应该是 111...若干的1
        // 最后的 n + 1及为变成2的倍(可不是为了补上的n-1,没有直接关系)
        return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
    }

上面代码中,最主要就是,n |= (n >>> 1,2,4,8,16)
例:还是以55(110111)举例
n | = n >>> 1
在这里插入图片描述

java中int占4个字节,也就是有32位,符号位在最高位,0为整数,1为负数

后面的以此类推,1 + 2 + 4 + 8 + 16 = 63 除了整数位,正好其他的位数都能为 1111… 并且1,2,4,8,16都为前一个数的倍数,正好可以把前一次位移运算的的1,当作下次的进行运算。 然后在最后的三元哪里 n+1及变为了2的倍数。
(上述的源码注释有写道,如果cap正好的2的倍数,如果没有-1)
例:8(1000)
转后
  15(1111) 
三元n+1
  16(10000)

最后感叹一下,还是要多学习,才能感受到自己是个井底之蛙,万不可死于安乐。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值