栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

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

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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的倍数
源码

    
     //                       传入的初始化容量
    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)

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

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/284110.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号