zoukankan      html  css  js  c++  java
  • 五、HashMap 索引计算

    从HashMap源码中,可以看到求容器下标值的方法,有两步,首先通过key值计算hash,然后用hash计算下标:

      计算hash:

      return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);

      计算下标,其下标值为:(n-1) & hash

     n = (tab = resize()).length;

    p = tab[i = (n - 1) & hash]

      即,是通过key的hash值和容器的大小减1,两者进行与运算,获取容器数组下标。这里使用与运算,其实蕴含了一个隐藏条件,即数组的大小n,必须是2的n次方,否则,计算出来的下标值i是无法覆盖这个范围[0, n-1]的。

      举个例子,假设两种情况,一种容器大小为10,不是2的幂,另外一种容器大小为16,刚好是2的4次方。

      则,对于第一种,n-1= 9, 二进制表示为 1001,任何值与该值进行与运算,都无法改变中间的两个0,只能改变首尾的两个1,因此结果范围就缩小了一倍

      而,对于第二种,n-1=15,二进制表示为 1111,该值与其他值与运算后,可以覆盖范围[0, 15],而这个范围刚好是数组的大小,因此只要hash值均匀分布,结果也是均匀的。

      实际上,只要数组大小是2的幂,则 (n-1) & hash 的结果等效于: hash % (n-1);即与运算、求余运算通过这个前提,实现了等效。

      而计算机中,与运算和求余运算,两个计算的效率肯定是前者更好。因为与运算,是直接对位进行逻辑与操作,属于cpu的底层支持的基础逻辑操作,但是求余运算可不是,应该是需要额外的算术运算单元支持的。可能这就是把数组大小规定为2的幂的原因之一,提高运算效率。

  • 相关阅读:
    python中matplotlib所绘制的图包含了很多的对象
    pd.concat()命令
    Java设计模式——外观模式
    Java设计模式——桥接模式
    Java基础面试
    java web解决表单重复提交
    Servlet 工作原理解析
    Mysql日期函数
    解决多个下拉框动态级联初始化问题
    window.parent与window.opener、window.showModalDialog的区别 opener和showModalDialog刷新父页面的方法
  • 原文地址:https://www.cnblogs.com/qiaoxin11/p/12827808.html
Copyright © 2011-2022 走看看