HashMap源码中的位运算符&详解
引言
最近在读HashMap源码的时候,发现在很多运算符替代常规运算符的现象。比如说用hash & (table.length-1) 来替代取模运算hash&(table.length);用if((e.hash & oldCap) == 0)判断扩容后元素的位置等等。
1.取模运算符%底层原理
总所周知,位运算&直接对二进制进行运算;而对于取模运算符%:a % b 相当于 a - a / b * b,底层实际上是除法器,究其根源也是由底层的减法和加法共同完成。所以其运行效率要远远小于位运算符&。
2.位运算符&如何实现取模功能
我们先来看两个例子
5 & 7 9 & 7
0101----5 1001----9
& &
0111----7 0111----7
= =
0101----5 0001----1
确实,hash & (table.length-1) 来实现了运算hash&(table.length)从二进制的角度来说,5%8实际上是将二进制5(0101)向右移动3位,而与7(0111)进行与运算实际上就是将位数向右移动三位。不过要注意的是,只有当length的长度为2^n时,结论才成立。
3.位运算符&在if((e.hash & oldCap) == 0)判断扩容后元素的位置
这是出自于JDK1.8中扩容函数resize()的一行代码,用于判断在扩容后原数组中的元素是否需要移动。举个例子:
0001 1010----26 0000 1010----10
& &
0001 0000----16 0001 0000----16
= =
0001 0000----非0 0000 0000-----0
利用hash值和oldCap进行与运算,很明显当结果大于0代表hash值大于oldCap时,下标位置变为旧数组的下标j + oldCap;若结果等于0代表小于oldCap,则下标位置不变。相比于JDK1.7重新计算每个元素的哈希值,通过高位运算(e.hash & oldCap)无疑效率更高。
到此这篇关于HashMap源码中的位运算符&详解的文章就介绍到这了,更多相关HashMap源码中的位运算符&内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
SpringBoot整合Keycloak实现单点登录的示例代码
本文主要介绍了SpringBoot整合Keycloak实现单点登录的示例代码,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下2022-03-03java如何获取用户登录ip、浏览器信息、SessionId
这篇文章主要介绍了java如何获取用户登录ip、浏览器信息、SessionId,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2021-11-11IntelliJ IDEA使用教程从入门到上瘾(2019图文版)
这篇文章主要介绍了IntelliJ IDEA使用教程从入门到上瘾(2019图文版),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧2018-12-12
最新评论