zoukankan      html  css  js  c++  java
  • 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)无疑效率更高。

  • 相关阅读:
    Sublime Text3快捷键大全
    IntelliJ IDEA常用快捷键(Mac)
    shell脚本执行错误 $' ':command not found
    Shell脚本中"command not found"报错处理
    Shell 数值、字符串比较
    Java线程池的构造以及使用
    Host 'xxx' is not allowed to connect to this MySQL server
    Linux下Mysql安装(tar安装)
    Linux下Mysql安装(RPM安装)
    Mac安装Mysql
  • 原文地址:https://www.cnblogs.com/EthanWong/p/13355822.html
Copyright © 2011-2022 走看看