【Java深入研究】11、深入研究hashmap中的hash算法
一、简介
大家都知道,HashMap中定位到桶的位置 是根据Key的hash值与数组的长度取模来计算的。
JDK8中的hash 算法:
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
取模算法:
hash(key)&(length-1)
二、深入分析
1、取模算法为什么用的是位与运算?
由于位运算直接对内存数据进行操作,不需要转成十进制,因此处理速度非常快。
对2的倍数取模,只要将数与2的倍数-1做按位与运算即可。
对原理感兴趣的可以参考【Java基础】14、位与(&)操作与快速取模
2、为什么不直接使用key.hashcode()进行取模运算?
我们知道hash的目的是为了尽量分布均匀。
取模做位与运算的时候,实际上刚刚开始数组的长度一般比较小,只利用了低16位,高16位是用不到的。这种情况下,产生hash冲突的概率会大大增加。
这样设计保证了对象的hashCode的高16位的变化能反应到低16位中,相比较而言减少了hash冲突的情况 。
选用亦或的方式是因为&和|都会使得结果偏向0或者1 ,并不是均匀的概念。
3、String的hashCode()深入分析
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value; for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
推导出的公式如下:
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
举个例子推导计算一下:
假设 n=3
i=0 -> h = 31 * 0 + val[0]
i=1 -> h = 31 * (31 * 0 + val[0]) + val[1]
i=2 -> h = 31 * (31 * (31 * 0 + val[0]) + val[1]) + val[2]
h = 31*31*31*0 + 31*31*val[0] + 31*val[1] + val[2]
h = 31^(n-1)*val[0] + 31^(n-2)*val[1] + val[2]
3.1、为什么使用31作为计算的因子呢?
- 选择质数作为乘子,会大大降低hash冲突的概率。质数的值越大,hash冲突率越低
- 31参与乘法运算,可以被 JVM 优化,
31 * i = (i << 5) - i
- 使用 101 计算 hash code 容易导致整型溢出,导致计算精度丢失
【Java深入研究】11、深入研究hashmap中的hash算法的更多相关文章
- HashMap中的hash算法总结
前言 算法一直是我的弱项,然而面试中基本是必考的项目,刚好上次看到一个HashMap的面试题,今天也来学习下 HashMap中的hash算法是如何实现的. 数学知识回顾 << : 左移运算 ...
- HashMap中的hash算法中的几个疑问
HashMap中哈希算法的关键代码 //重新计算哈希值 static final int hash(Object key) { int h; return (key == null) ? 0 : (h ...
- hashCode及HashMap中的hash()函数
一.hashcode是什么 要理解hashcode首先要理解hash表这个概念 1. 哈希表 hash表也称散列表(Hash table),是根据关键码值(Key value)而直接进行访问的数据结构 ...
- [ 转载 ]hashCode及HashMap中的hash()函数
hashCode及HashMap中的hash()函数 一.hashcode是什么 要理解hashcode首先要理解hash表这个概念 1. 哈希表 hash表也称散列表(Hash table),是 ...
- HashMap 中的 hash 函数
1. 什么是 hash 函数 hash 函数,即散列函数,或叫哈希函数.它可以将不定长的输入,通过散列算法转换成一个定长的输出,这个输出就是散列值.需要注意的是,不同的输入通过散列函数,也可能会得到同 ...
- HashMap中的hash函数
在写一个HashSet时候有个需求,是判断HashSet中是否已经存在对象,存在则取出,不存在则add添加.HashSet也是通过HashMap实现,只用了HashMap的key,value都存储一个 ...
- 图像相似度中的Hash算法
度量两张图片的相似度有许多算法,本文讲介绍工程领域中最常用的图片相似度算法之一--Hash算法.Hash算法准确的说有三种,分别为平均哈希算法(aHash).感知哈希算法你(pHash) ...
- PHP中各种Hash算法性能比较
国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...
- php中各种hash算法的执行速度比较
更多内容推荐微信公众号,欢迎关注: PHP中的Hash函数很多,像MD4.MD5.SHA-1.SHA-256.SHA-384.SHA-512等我们比较常见,那么各个哈希的执行速度呢? $algos = ...
随机推荐
- axios跨域处理
本质分析: 因为axios在vue中利用中间件http-proxy-middleware做了一个本地的代理服务A,相当于你的浏览器通过本地的代理服务A请求了服务端B,浏览器通过服务A并没有跨域,因此就 ...
- Scrapy笔记09- 部署
Scrapy笔记09- 部署 本篇主要介绍两种部署爬虫的方案.如果仅仅在开发调试的时候在本地部署跑起来是很容易的,不过要是生产环境,爬虫任务量大,并且持续时间长,那么还是建议使用专业的部署方法.主要是 ...
- maker使用说明书
1.以自带的示例数据为例 dpp_contig.fasta dpp_est.fasta dpp_protein.fasta te_proteins.fasta 2.生成控制文件 控制文件是特定于运行的 ...
- vue之非父子通信
一.非父子通信: 思路: 找个中间存储器,组件一把信息放入其中,组件二去拿 代码如下: let hanfei = new Vue(); # 实列化个空的vue对象,作为中间存储器来时间 ...
- selenium--单选下拉列表
下拉选择 from selenium import webdriver from time import sleep driver = webdriver.Chrome() driver.get(&q ...
- 2019年底前的web前端面试题初级-web标准应付HR大多面试问题
作者 | Jeskson来源 | 达达前端小酒馆 问:你知道在css中,html的标签元素分多少中不同的类型吗? 答:大体可分三种:1,块状元素,2,内联元素,3,内联块状元素 块级元素:就是每个块级 ...
- webpack的一些坑
最近自己着手做一个小的Demo需要webpack,目前版本号是4.41.2,想使用的版本是3.6.0,因3x版本和4x版本很多地方不同,所以在安装过程中也是很多坎坷,下面是遇到的一些坑,和一些解决办法 ...
- 【cf比赛记录】Educational Codeforces Round 78 (Rated for Div. 2)
比赛传送门 A. Shuffle Hashing 题意:加密字符串.可以把字符串的字母打乱后再从前面以及后面接上字符串.问加密后的字符串是否符合加密规则. 题解:字符串的长度很短,直接暴力搜索所有情况 ...
- C语言-memset()
1. memset()函数原型是extern void *memset(void *buffer, int c, int count) buffer:为指针或是数组, c:是赋给buff ...
- 【Gamma】Scrum Meeting 8
前言 会议定点:大运村公寓 会议时间:2019/6/7 会议目的:分配任务,准备宣传 一.任务进度 组员 上周任务进度 下阶段任务 大娃 辅助做好引导录屏 优化辅助模型 二娃 撰写会议博客 撰写会议博 ...