未经本人容许,禁止转载

大家都知道(jdk1.8)HashMap中计算数组下标是HashMap的核心算法。小编今天在看HashMap源码中看到了hash(Object key)方法百思不得其解。小编问百度,查找相关博客,甚至连HashMap的关于hash(Object key)英文解释都看了。但是都只是说了为了尽量均匀,没有详细讲。小编今天为大家详细讲解一下这两个问题。

HashMap中hash(Object key)的原理,为什么这样做?

先看下hash(Object key)方法,详细大家基本都能看懂,但是知道这一步(h = key.hashCode()) ^ (h >>> 16)原因的人很少。

 static final int hash(Object key) {int h;return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);}

首先这个方法的返回值还是一个哈希值。为什么不直接返回key.hashCode()呢?还要与 (h >>> 16)异或。首先要了解以下知识点:

必备知识点.:^ 运算  >>>运算  &运算。

1. h >>> 16 是什么,有什么用?

h是hashcode。h >>> 16是用来取出h的高16,(>>>是无符号右移)   如下展示:

0000 0100 1011 0011  1101 1111 1110 0001>>> 16 0000 0000 0000 0000  0000 0100 1011 0011

2. 为什么 h = key.hashCode()) 与 (h >>> 16) 异或

讲到这里还要看一个方法indexFor,在jdk1.7中有indexFor(int h, int length)方法。jdk1.8里没有,但原理没变。下面看下1.7源码

1.8中用tab[(n - 1) & hash]代替但原理一样。

static int indexFor(int h, int length) {return h & (length-1);
}

这个方法返回值就是数组下标。我们平时用map大多数情况下map里面的数据不是很多。这里与(length-1)相&,

但由于绝大多数情况下length一般都小于2^16即小于65536。所以return h & (length-1);结果始终是h的低16位与(length-1)进行&运算。如下例子(hashcode为四字节)

例如1:为了方便验证,假设length为8。HashMap的默认初始容量为16

length = 8;  (length-1) = 7;转换二进制为111;

假设一个key的 hashcode = 78897121 转换二进制:100101100111101111111100001,与(length-1)& 运算如下

    0000 0100 1011 0011 1101 1111 1110 0001&运算0000 0000 0000 0000 0000 0000 0000 0111=   0000 0000 0000 0000 0000 0000 0000 0001 (就是十进制1,所以下标为1)

上述运算实质是:001 与 111 & 运算。也就是哈希值的低三位与length与运算。如果让哈希值的低三位更加随机,那么&结果就更加随机,如何让哈希值的低三位更加随机,那么就是让其与高位异或。

补充知识:

当length=8时    下标运算结果取决于哈希值的低三位

当length=16时  下标运算结果取决于哈希值的低四位

当length=32时  下标运算结果取决于哈希值的低五位

当length=2的N次方, 下标运算结果取决于哈希值的低N位。

3. 原因总结

由于和(length-1)运算,length 绝大多数情况小于2的16次方。所以始终是hashcode 的低16位(甚至更低)参与运算。要是高16位也参与运算,会让得到的下标更加散列。

所以这样高16位是用不到的,如何让高16也参与运算呢。所以才有hash(Object key)方法。让他的hashCode()和自己的高16位^运算。所以(h >>> 16)得到他的高16位与hashCode()进行^运算。

4. 为什么用^而不用&和|

因为&和|都会使得结果偏向0或者1 ,并不是均匀的概念,所以用^。

这就是为什么有hash(Object key)的原因。

下一遍,小编为大家讲解为什么HashMap数组长度是2的幂次方(2^n)。

HashMap中hash(Object key)原理,为什么(hashcode >>> 16)。相关推荐

  1. HashMap中hash(Object key)原理(hashcode >>> 16)

    大家都知道(jdk1.8)HashMap中计算数组下标是HashMap的核心算法.小编今天在看HashMap源码中看到了hash(Object key)方法百思不得其解.小编问百度,查找相关博客,甚至 ...

  2. Java中hashCode()方法以及HashMap()中hash()方法

    Java的Object类中有一个hashCode()方法: public final native Class<?> getClass(); public native int hashC ...

  3. HashMap中hash函数怎么是实现的?

    我们可以看到,在 hashmap 中要找到某个元素,需要根据 key 的 hash 值来求得对应数组中的位置.如何计算这个位置就是 hash 算法. 前面说过,hashmap 的数据结构是数组和链表的 ...

  4. hash算法_阿里面试官:讲一下Hashmap中hash算法!

    注:本文内容全部基于jdk8讲述. 相信很多人都知道,在JDK8中,HashMap的容量总是2的n次幂,那么这么设计的目的究竟是什么呢?我可不可以将默认的初始容量从16改成20呢,扩容的时候我可不可以 ...

  5. [Java 8 HashMap 详解系列]7.HashMap 中的红黑树原理

    [Java 8 HashMap 详解系列] 文章目录 1.HashMap 的存储数据结构 2.HashMap 中 Key 的 index 是怎样计算的? 3.HashMap 的 put() 方法执行原 ...

  6. mysql的hash分区_MySQL中hash和key分区值的计算方法

    MySQL中hash和key分区值的计算方法 mysql中有一种叫作key作为partition key的类型.来看看记录是怎么分布的 对于hash 分区,使用%操作符,每个partition key ...

  7. HashMap 中 hash 冲突的解决方法及原理分析

    我们最先衰老的不是容貌,而是不顾一切的闯劲.有时候,要敢于背上超出自己预料的包袱,真的努力后,你会发现自己要比想象的优秀很多. HashMap冲突的解决方法比较考验一个开发者解决问题的能力. 在Jav ...

  8. String中的hashcode缓存以及HashMap中String作key的好处

    目录 hashcode方法源码 不可变性 缓存HashCode 线程安全 hashcode方法源码 public int hashCode() {int h = hash;if (h == 0 &am ...

  9. hashmap中的key是有序的么_HashMap?面试?我是谁?我在哪

    (给ImportNew加星标,提高Java技能) 转自:卓庆森 https://www.cnblogs.com/zhuoqingsen/p/8577646.html 现在是晚上11点了,学校屠猪馆的自 ...

最新文章

  1. android onLayout死循环
  2. 【Python小脚本】实现王者农药自动刷金币啦~啦啦啦走跟我一起组队~
  3. 压力测试工具Jemeter安装及使用
  4. Matlab神经网络十讲(2): Create Configuration Train NeuralNet
  5. 双11又来了,网友:比数学考试都难
  6. 将数据转化成字符串时:用字符串的链接 还是 StringBuilder
  7. Java中锁的使用和实现
  8. 安卓系统曝漏洞!有人可能正在用你的手机秘密拍照
  9. 00后网购消费报告:超九成用户跟好友拼过单 手机数码花销最大
  10. 2019.7.17东湖大数据页面三
  11. [BZOJ1030][JSOI2007]文本生成器
  12. 独立ip 公司文件服务器,企业在外贸建站时,为什么要选择独立IP的服务器?
  13. 微信小程序中的网络请求
  14. 32个高效思维模型,快速提升你的思考力!
  15. 在excel筛选出某一列多个重复值
  16. Https比Http速度慢具体分析
  17. 夜深人静写算法(十五)- 完全背包
  18. VB.NET 打开Excel文件,读取Excel内容,添加到DataGridView中并显示
  19. iOS调试技巧(转载)
  20. Mac-Mac上如何制作GIF动图

热门文章

  1. 神经网络与矩阵表示之间的恩怨情仇
  2. iptables ipset详解
  3. 说说开源中国社区的愚人节
  4. 人大金仓数据库-表的定义
  5. AWT,SWT缩小图片消除锯齿的平滑处理
  6. 分布式事务解决方案和原理
  7. 网站被劫持怎么办?传奇网站打开跳到其他站的解决方法
  8. 《桃花源记》古文鉴赏
  9. MySQL卸载干净的全过程
  10. Java 开发环境搭建