HashMap中确定数组位置为什么要用hash进行扰动
HashMap数据存储的过程先根据key获得hash值,通过 (n - 1) & hash
判断当前元素存放的位置(这里的 n 指的是数组的长度),如果当前位置存在元素的话,就判断该元素与要存入的元素的 hash 值以及 key 是否相同,如果相同的话,直接覆盖,不相同就通过拉链法解决冲突。
其中,jdk1.8中扰动函数hash的源码:
static final int hash(Object key) {
int h;
// key.hashCode():返回散列值也就是hashcode
// ^ :按位异或
// >>>:无符号右移,忽略符号位,空位都以0补齐
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
其中看到在获得hash值时将key的hashCode异或上其无符号右移16位,Hashmap这么做原因:
防止一些实现比较差的 hashCode() 方法,使用扰动函数之后可以减少碰撞,进一步降低hash冲突的几率。
打个比方, 当我们的数组长度n为16的时候,哈希码(字符串“abcabcabcabcabc”的key对应的哈希码)对(16-1)与操作,对于多个key生成的hashCode,只要哈希码的后4位为0,不论不论高位怎么变化,最终的结果均为0。 如下图所示:
1954974080(HashCode) | 111 0100 1000 0110 1000 1001 1000 0000 |
2^4-1=15(length-1) | 000 0000 0000 0000 0000 0000 0000 1111 |
&运算 | 000 0000 0000 0000 0000 0000 0000 0000 |
而加上高16位异或低16位的“扰动函数”后,结果如下:
原HashCode | 1954974080 | 111 0100 1000 0110 1000 1001 1000 0000 |
(>>>16)无符号右移16位 | 29830 | 000 0000 0000 0000 0111 0100 1000 0110 |
^(异或)运算 | 1955003654 | 111 0100 1000 0110 1111 1101 0000 0110 |
2^4-1=15(length-1) | 15 | 000 0000 0000 0000 0000 0000 0000 1111 |
&(与)运算 | 6 | 000 0000 0000 0000 0000 0000 0000 0110 |
可以看到: 扰动函数优化前:1954974080 % 16 = 1954974080 & (16 - 1) = 0 扰动函数优化后:1955003654 % 16 = 1955003654 & (16 - 1) = 6 很显然,减少了碰撞的几率。
参考:https://zhuanlan.zhihu.com/p/76735726
HashMap中确定数组位置为什么要用hash进行扰动的更多相关文章
- JS查找数组中出现的位置及个数
查找某个值在数组中出现的位置 var attr = [1,4,5,3,2,7,6,9]; var zhao = 8; var sy = -1; for(var i=0;i<attr.length ...
- MongoDB 学习笔记之 从数组中删除元素和指定数组位置
从数组中删除元素: 从数组中删除单个元素: db.ArrayTest.updateOne({ "name" : "Bill"},{$pop: {"ad ...
- 如果两个对象具有相同的哈希码,但是不相等的,它们可以在HashMap中同时存在吗?
如果两个对象具有相同的哈希码,但是不相等的,它们可以在HashMap中同时存在吗? ----答案是 可以 原因: 在hashmap中,由于key是不可以重复的,他在判断key是不是重复的时候就判断了h ...
- JDK1.8 HashMap中put源码分析
一.存储结构 在JDK1.8之前,HashMap采用桶+链表实现,本质就是采用数组+单向链表组合型的数据结构.它之所以有相当快的查询速度主要是因为它是通过计算散列码来决定存储的位置.Hash ...
- HashMap中的散列函数、冲突解决机制和rehash
一.概述 散列算法有两个主要的实现方式:开散列和闭散列,HashMap采用开散列实现. HashMap中,键值对(key-value)在内部是以Entry(HashMap中的静态内部类)实例的方式存储 ...
- HashMap中的resize以及死链的情况
之前我已经写过关于HashMap的内容了:http://www.cnblogs.com/wang-meng/p/7545725.html 我们都知道HashMap是线程不安全的, 如果多线程来访问会有 ...
- 关于hashMap中 计算hashCode的逻辑推理(二)
hashMap中,为了使元素在数组中尽量均匀的分布,所以使用取模的算法来决定元素的位置.如下: //方法一: static final int hash(Object key){//jdk1.8 in ...
- HashMap中的hash算法总结
前言 算法一直是我的弱项,然而面试中基本是必考的项目,刚好上次看到一个HashMap的面试题,今天也来学习下 HashMap中的hash算法是如何实现的. 数学知识回顾 << : 左移运算 ...
- hashCode及HashMap中的hash()函数
一.hashcode是什么 要理解hashcode首先要理解hash表这个概念 1. 哈希表 hash表也称散列表(Hash table),是根据关键码值(Key value)而直接进行访问的数据结构 ...
随机推荐
- 树莓派GPIO引脚标识图
- oracle基本语句(第四章、数据库安全管理)
1.用SYS用户以SYSDBA身份登录SQL Plus,使用DBA_USERS视图查看用户信息: SELECT USERNAME, ACCOUNT_STATUS, CREATED FROM DBA_U ...
- 【NOIP2016提高A组模拟10.15】算循环
题目 分析 一步步删掉循环, 首先,原式是\[\sum_{i=1}^n\sum_{j=1}^m\sum_{k=i}^n\sum_{l=j}^m\sum_{p=i}^k\sum_{q=j}^l1\] 删 ...
- Help library 安装arcobjects for .NET异常问题
新建一个reg文件写入,也可以导出一个reg文件在上面重新写入. Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\CLSID\{9DAA ...
- ASP教程:gb2312和utf-8乱码问题解决
文章为转载:https://www.xp.cn/b.php/31663.html 尊重作者版权 今天做网站的时候,客户要一个博客,于是就利用了本博客所用的程序pjblog.经常做网站的人都知道,在同一 ...
- 装sqlserver2005驱动解决firedac连接sql2000问题
装了sqlserver2005驱动, 系统里装的sqlserver2012也能连上sql2000了. 当然firedac连sql2000也没问题了.设置个ODBCAdvanced为SQL Native ...
- spring boot2.0.2,<-1.4.8
DataSourceBuilder cannot be resolved DataSourceBuilder cannot be resolved to a type RelaxedPropertyR ...
- matlab中画三维图形
这里主要讲述两个方法用matlab画三维图形: 1.mesh函数 先看一个简单的例子: x = ::; y = ::; [X, Y] = meshgrid(x, y); Z = zeros(,); Z ...
- tensorflow版本介绍
软件的生命周期中一般分4个版本,RC 和 Beta分别是其中2种.如下是4种的解释: alpha版:内部测试版.α是希腊字母的第一个,表示最早的版本,一般用户不要下载这个版本,这个版本包含很多BUG, ...
- 论文阅读:Stateless Network Functions: Breaking the Tight Coupling of State and Processing
摘要: 无状态网络功能是一个新的网络功能虚拟化架构,解耦了现有的网络功能设计到无状态处理组件以及数据存储层,在打破紧密耦合的同时,实现了更具可伸缩性和可恢复性的网络功能基础设施.无状态NF处理实例是围 ...