/**
* Computes key.hashCode() and spreads (XORs) higher bits of hash
* to lower. Because the table uses power-of-two masking, sets of
* hashes that vary only in bits above the current mask will
* always collide. (Among known examples are sets of Float keys
* holding consecutive whole numbers in small tables.) So we
* apply a transform that spreads the impact of higher bits
* downward. There is a tradeoff between speed, utility, and
* quality of bit-spreading. Because many common sets of hashes
* are already reasonably distributed (so don't benefit from
* spreading), and because we use trees to handle large sets of
* collisions in bins, we just XOR some shifted bits in the
* cheapest possible way to reduce systematic lossage, as well as
* to incorporate impact of the highest bits that would otherwise
* never be used in index calculations because of table bounds.
*/
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

上次在面试中被问及一个问题:如果直接拿key的内存地址的long值与table的长度做取余操作(%),有什么不好?

我做了一番研究。

first = tab[(n - 1) & hash]

首先,在计算一个key在table中的位置时,用的是table的长度减1,与hash值取位与的结果。而不是取余(%)操作。

如果一个table的长度为8,那么n=8 (1000),n-1=7 (111),如果hash是什么值,取and的结果一定是000 ~ 111 之间,即0-7,正好对应table的index的范围。

注释中写道,Because the table uses power-of-two masking, sets of hashes that vary only in bits above the current mask will always collide.

翻译过来就是:table的长度总是2的n次幂,如果一组hash值只是在(111....1111)之上的高位互相不同,那么它们与(n-1) 位与 的结果总会碰撞。

一句话概括就是,key只有与(n-1)低位为1的长度相同位参与了hash碰撞的计算,高位没有体现出来。

JDK作者的解决方案是:(h = key.hashCode()) ^ (h >>> 16), JDK的doc中一开始说: spread higher bits of hash to lower

将高位的影响传播到低位,这样与(n-1)位与的计算,高低位就同时参与了。

我们都知道,一个int值是32位的,hash >>> 16 的含义就是右移16位,左边以0补齐。移位的结果是,低16位被抛弃,原高16位变成新低16位,新高16位用0补充。

0与0异或是0,0与1异或是1,即一个bit与0异或结果不变。 所以,hash xor (hash >>> 16) 的最终结果是:高16位不变,低16位与高16位异或。

如果 (n-1) 的二进制表示有16位,那么 n = 2的16次方 =  65536,hashmap的容量只要不大于65536,都是高低混合之16位在参与碰撞检测。

hashmap的hash方法源doc解读的更多相关文章

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

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

  2. HashMap之Hash碰撞源码解析

    转自:https://blog.csdn.net/luo_da/article/details/77507315 https://www.cnblogs.com/tongxuping/p/827619 ...

  3. AbstractCollection类中的 T[] toArray(T[] a)方法源码解读

    一.源码解读 @SuppressWarnings("unchecked") public <T> T[] toArray(T[] a) { //size为集合的大小 i ...

  4. hashmap的put方法源码分析

    put主源码如下: public V put(K key, V value) { if (key == null) return putForNullKey(value); int hash = ha ...

  5. hashMap 源码解读理解实现原理和hash冲突

    hashMap 怎么说呢. 我的理解是 外表是一个set 数组,无序不重复 . 每个set元素是一个bean ,存着一对key value 看看代码吧 package test; import jav ...

  6. 关于HashMap中hash()函数的思考

    关于HashMap中hash()函数的思考 JDK7中hash函数的实现   static int hash(int h) { h ^= (h >>> 20) ^ (h >&g ...

  7. HashMap的hash分析

    哈希 Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入,通过散列算法,变换成固定长度的输出,该输出就是散列值.这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空 ...

  8. JDK1.8中HashMap的hash算法和寻址算法

    JDK 1.8 中 HashMap 的 hash 算法和寻址算法 HashMap 源码 hash() 方法 static final int hash(Object key) { int h; ret ...

  9. jdk1.8.0_45源码解读——HashMap的实现

    jdk1.8.0_45源码解读——HashMap的实现 一.HashMap概述 HashMap是基于哈希表的Map接口实现的,此实现提供所有可选的映射操作.存储的是<key,value>对 ...

随机推荐

  1. Cortex-M3 操作模式与特权等级

    Cortex-M3支持2个模式(Handler模式.线程模式)和2个特权等级(特权级.非特权级). 当处理器处在线程模式时,既可以使用特权级,也可以使用非特权级. 当处理器处在Handler模式时,总 ...

  2. LC 712. Minimum ASCII Delete Sum for Two Strings

    Given two strings s1, s2, find the lowest ASCII sum of deleted characters to make two strings equal. ...

  3. Dev中GridView——背景颜色改变

    DevExpress.XtraGrid.Views 设置指定行的背景颜色 1.事件:CustomDrawCell2.示例: private void gridView1_CustomDrawCell( ...

  4. JMeter4.0分布式调度压测部署

    我们在Loadrunner学过使用Load Generator做肉鸡, 通过Controller来进行脚本和权重的分配来进行分布式压测, Jmeter作为当今的网红性能测试工具,这个功能必须是少不了的 ...

  5. Jmeter测试结果分析(下)

    Jmeter测试结果分析(下) 前文再续,续接上一回.上一篇讲了如何利用Assertion将测试结果进行初步的筛选.那么,当我们拿到了测试结果之后,我们应该如何去看待它们呢?它们又是怎么来的呢? 一. ...

  6. kvm简介及创建虚拟化安装(1)

    kvm虚拟化介绍 一.虚拟化分类 1.虚拟化,是指通过虚拟化技术将一台计算机虚拟为多台逻辑计算机.在一台计算机上同时运行多个逻辑计算机,每个逻辑计算机可运行不同的操作系统,并且应用程序都可以在相互独立 ...

  7. 实现文件上传功能(FileUpload组件)

    文件上传: 项目中经常用到文件上传. 自己实现文件上传,使用文件上传组件fileupload组件 1.指定表单类型为文件上传, enctype=”multipart/form-data” 2.提交方式 ...

  8. Leetcode之动态规划(DP)专题-338. 比特位计数(Counting Bits)

    Leetcode之动态规划(DP)专题-338. 比特位计数(Counting Bits) 给定一个非负整数 num.对于 0 ≤ i ≤ num 范围中的每个数字 i ,计算其二进制数中的 1 的数 ...

  9. java-最大公约数

    4和2的最大公约数是2呀

  10. 搭建elk集群 disabled in libcurl elasticsearch-6.2.2 更新license 版本

    0.logstash的部分配置 output { stdout {codec => rubydebug} elasticsearch { hosts => ["172.31.25 ...