hashmap的hash方法源doc解读
/**
* 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解读的更多相关文章
- Java中hashCode()方法以及HashMap()中hash()方法
Java的Object类中有一个hashCode()方法: public final native Class<?> getClass(); public native int hashC ...
- HashMap之Hash碰撞源码解析
转自:https://blog.csdn.net/luo_da/article/details/77507315 https://www.cnblogs.com/tongxuping/p/827619 ...
- AbstractCollection类中的 T[] toArray(T[] a)方法源码解读
一.源码解读 @SuppressWarnings("unchecked") public <T> T[] toArray(T[] a) { //size为集合的大小 i ...
- hashmap的put方法源码分析
put主源码如下: public V put(K key, V value) { if (key == null) return putForNullKey(value); int hash = ha ...
- hashMap 源码解读理解实现原理和hash冲突
hashMap 怎么说呢. 我的理解是 外表是一个set 数组,无序不重复 . 每个set元素是一个bean ,存着一对key value 看看代码吧 package test; import jav ...
- 关于HashMap中hash()函数的思考
关于HashMap中hash()函数的思考 JDK7中hash函数的实现 static int hash(int h) { h ^= (h >>> 20) ^ (h >&g ...
- HashMap的hash分析
哈希 Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入,通过散列算法,变换成固定长度的输出,该输出就是散列值.这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空 ...
- JDK1.8中HashMap的hash算法和寻址算法
JDK 1.8 中 HashMap 的 hash 算法和寻址算法 HashMap 源码 hash() 方法 static final int hash(Object key) { int h; ret ...
- jdk1.8.0_45源码解读——HashMap的实现
jdk1.8.0_45源码解读——HashMap的实现 一.HashMap概述 HashMap是基于哈希表的Map接口实现的,此实现提供所有可选的映射操作.存储的是<key,value>对 ...
随机推荐
- Vue -3:单文件组件
在很多 Vue 项目中,我们使用 Vue.component 来定义全局组件,紧接着用 new Vue({ el: '#container '}) 在每个页面内指定一个容器元素. 这种方式在很多中小规 ...
- css中设置table中的td内容自动换行
word-break:break-all和word-wrap:break-word都是能使其容器如DIV的内容自动换行. 它们的区别就在于: 1,word-break:break-all 例如div宽 ...
- 五十七:flask文件上传之使用flask-wtf验证上传的文件
1.安装:pip install flask-wtf2.定义表单验证的时候,对文件的字段,需使用:FileField3.验证器从flask_wtf.file中导入,FileRequired为验证文件必 ...
- 在Excel工作表单元格中引用当前工作表名称
在Excel工作表单元格中引用当前工作表名称 有多份Excel表格表头标题都为"××学校第1次拉练考试××班成绩表",由于工作表结构都是一样的,所以我每次都是复制工作表然后编辑修改 ...
- docker笔记、常遇问题、常用命令
启动一个容器并且进到里面,退出后,容器结束 [root@bogon ~]# docker run --name mynginx -it nginx 启动一个容器,退出后自动删除 [root@bogon ...
- C基础知识(14):命令行参数
命令行参数是使用main()函数参数来处理的,其中,argc是指传入参数的个数,argv[]是一个指针数组,指向传递给程序的每个参数. 应当指出的是,argv[0]存储程序的名称,argv[1]是一个 ...
- BeanPostProcessor详解
转自: https://www.jianshu.com/p/d26e8ec9c077? BeanPostProcessor也称为Bean后置处理器,它是Spring中定义的接口,在Spring容器的创 ...
- 【MapReduce】一、MapReduce简介与实例
(一)MapReduce介绍 1.MapReduce简介 MapReduce是Hadoop生态系统的一个重要组成部分,与分布式文件系统HDFS.分布式数据库HBase一起合称为传统Hadoop的三 ...
- 【VS开发】【图像处理】直方图均衡与平台直方图
目录(?)[-] 直方图均衡化Histogram Equalization 直方图均衡化的主要过程 一个简单的例子 关键的代码实现 平台直方图及均衡化 平台直方图的概念 平台阈值的确定 关键代码实现 ...
- LeetCode-求最长回文子序列
题目:给定一个字符串,求它的最长回文子串 /*求最长回文子串,以当前字符为中心,向两边同时拓展*/ string longestPalindrome(string s) { int len = s.l ...