/**
* 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. leetcode334 递增的三元子序列

    class Solution { public: bool increasingTriplet(vector<int>& nums) { //使用双指针: int len=nums ...

  2. BFC是什么?有什么作用?

    BFC(Block Formatting Context)直译为“块级格式化范围”. 一.常见定位方案 在讲 BFC 之前,我们先来了解一下常见的定位方案,定位方案是控制元素的布局,有三种常见方案: ...

  3. 内存数据库:memcached与redis技术的对比试验

    本文以高性能nginx服务器为应用背景,想利用缓存技术来减轻系统负荷,加快响应时间,从而增加web服务器的吞吐量. redis是一种分布式内存数据库,memcached是一种内存缓存技术,它们都采用k ...

  4. Script Form商业报表程序设计

    Script Form 是SAP所提供的一款强大的报表设设计工具. 一.Script Form主要工具包括如下: 1)Form Painter:格式绘制器,用于格式的设定.TCoce:SE71. 2) ...

  5. python-https状态码

    HTTP状态码状态码的职责是当客户端向服务器发送请求时,描述返回的请求结果.借助状态码,用户可以知道服务器端是正常处理了请求,还是出现了错误. 状态码的类别 >>>状态码 类别 说明 ...

  6. QT5中编译存在的几个问题(LNK2019,构造函数不能有返回类型)

    1. 自己构造新类,注意必须在头文件最后加上分号 写个c++类报“构造函数不能有返回类型”, 谷歌一下,才找到原因: 原来是我定义的类后面没有用“:”结尾,构造函数默认把整个类作为返回值了 2. 新建 ...

  7. 【Python基础】lpthw - Exercise 47 自动化测试

    一.自动化测试的目的 利用自动化的测试代码取代手动测试,使得程序中的一些初级bug可以被自动检出,而无需人工进行重复繁琐的测试工作. 二.编写测试用例 利用上一节编写的skeleton,这次在proj ...

  8. 【OpenJ_Bailian - 2790】迷宫(bfs)

    -->迷宫  Descriptions: 一天Extense在森林里探险的时候不小心走入了一个迷宫,迷宫可以看成是由n * n的格点组成,每个格点只有2种状态,.和#,前者表示可以通行后者表示不 ...

  9. OpenStack组件——Nova计算资源管理

    1.nova介绍 Nova 是 OpenStack 最核心的服务,负责维护和管理云环境的计算资源.OpenStack 作为 IaaS 的云操作系统,虚拟机生命周期管理也就是通过 Nova 来实现的. ...

  10. 【Deep Learning Nanodegree Foundation笔记】第 10 课:Sentiment Analysis with Andrew Trask

    In this lesson, Andrew Trask, the author of Grokking Deep Learning, will walk you through using neur ...