HashMap中hash方法的作用(详解)

1 篇文章 0 订阅
订阅专栏
HashMap的hash方法用于计算key的哈希码,通过高位与低位异或增强随机性,减少碰撞。在计算数组下标时使用(&)代替%运算,前提是数组长度为2的n次方。该方法旨在优化存储分布,提高查找效率。
摘要由CSDN通过智能技术生成

首先,hash方法用来干什么?

在搞清楚原理之前,我们先站在巨人的肩膀浅浅了解一下hash方法的本质作用。

实质上,它的作用很朴素,就是用key值通过某种方式计算出一个hash码

而且这个hash码我们后面要用来计算key存在底层数组的下标,所以它必须保持一定的随机性,让计算出的数组元素下标更加均衡分布,减少碰撞,其实就是更大程度上的避免hash冲突。

注:保持随机性这一性质,只有在hash方法计算hash值这一步会有所体现,后面的取模运算只是单独的为了取到余数,与保证随机性没有关系

Hash方法是什么?

这里先直观的给出它的源码:

参数 key 需要计算哈希码的键值。
key == null ? 0 : (h = key.hashCode()) ^ (h >>> 16) :这是一个三目运算符,看似复杂,其实很好理解。
逻辑就是:如果键值为null,则哈希码为 0 (依旧是说如果键为 null ,则存放在第一个位置);否则,通过调用 hashCode() 方 法获取键的哈希码,并将其与右移16 位的哈希码进行异或运算。
^ 运算符:异或运算符是 Java 中的一种位运算符,它用于将两个数的二进制位进行比较,如果相同则为 0,不同则为 1
 >>> 16 将哈希码向右移动 16 位,相当于将原来的哈希码分成了两个 16 位的部分。最终返回的是经过异或运算后得到的哈希码值。

这短短的一行代码,汇聚不少计算机巨佬们的聪明才智。

理论上,哈希值(即hashcode方法返回的值)是一个 int 类型,大家都知道int型在java中占4个字节,即32位,范围从 -2147483648 2147483648 。前后加起来大概 40 亿的映射空间,只要哈希值映射得比较均匀松散,一般是不会出现哈希碰撞(哈希冲突会降低 HashMap 的效率)。
但问题是一个 40 亿长度的数组,内存是放不下的。 HashMap 扩容之前的数组初始大小只有 16 ,所以这个哈希值是不能直接拿来用的,用之前要和数组的长度做取模运算(前文提到的 (n - 1) & hash ),用得到的余数来访问数组下标才行。

对h ^ h>>>16如何理解?

上面的h其实就是我们调用key的hashcode()方法得到的hashcode值,我们将它右移16位(因为是int型,所以总共是32位),前面16位补0,然后我们让它与原本的hashcode值进行异或,因为异或的逻辑是不同为1,相当于就是前16位与后16位进行会进行一次异或,占据最终返回的hash的后16位,然后前16位与进行补位的16个0进行异或,占据最终返回的hash的前16位,得到最终return的hash码。

上面的流程可以参考下面的图进行思考:

 

这样大家可能会比较疑惑,这么翻来覆去是为了啥呀,其实都是为了一个:hash码的随机性,目的还是为了避免hash冲突,毕竟hash冲突会降低HashMap的效率。

综上所述, hash 方法是用来做哈希值优化的 ,把哈希值右移 16 位,也就正好是自己长度的一半,之后与原哈希值做异或运算,这样就混合了原哈希值中的高位和低位,增大了随机性。

 

计算好了hash值,然后我们怎么使用hash值计算下标?

我们使用(n - 1)& hash的方式获取下标;(其实就是取模运算)

大家可能会比较好奇,要进行取模运算难道不该用% 吗?为什么要用位运算 &呢

这是因为%虽然确实可以实现,但是实际效率却还是不如&

并且我们的&能够取代%,是要有一个前提条件的:

只有当 b 2 n 次方时,才存在这样一个公式:a % b = a & (b-1)

我们可以对其进行一个验证:

我们来验证一下,假如 a = 14 b = 8 ,也就是 2^3 n=3
14%8 (余数为 6), 14 的二进制为 1110 8 的二进制 1000 8-1 = 7 7 的二进制为 0111 1110&0111=0110 ,也就是 0 * 2^0+1 * 2^1+1 * 2^2+0 * 2 ^3=0+2+4+0=6 14%8 刚好也等于 6
害,计算机就是这么讲道理,没办法
也就是说,只有数组长度是2的n次方时,使用&才会取余成功,这也是为什么,我们对hashmap进行扩容时,必须是2倍扩容了
为什么会这么巧,刚好二者就相同了呢,这与一个低位掩码的概念有关,这里我们先不细讲。

顺着上一个问题的图,我们再看这个步骤进行理解:

 

知道了hash方法的原理以及并将其计算出来,我们还需要知道:

 hash方法在哪里被用到?

1.首先当然是我们最经典的put方法 ,后面的putval会通过hash值来计算下标

2.其次是我们使用get方法获取元素时,会调用getNode方法,其中用到hash值

小结

hash 方法的主要作用是将 key 的 hashCode 值进行处理,得到最终的哈希值。由于 key 的hashCode 值是 不确定的,可能会出现哈希冲突,因此需要将哈希值通过一定的算法映射到HashMap 的实际存储位置上。
hash 方法的原理是,先获取 key 对象的 hashCode 值,然后将其高位与低位进行异或操作,得到一个新的哈希值。为什么要进行异或操作呢?因为对于 hashCode 的高位和低位,它们的分布是比较均匀的,如果只是简单地将它们加起来或者进行位运算,容易出现哈希冲突,而异或操作可以避免这个问题。然后将新的哈希值取模(mod),得到一个实际的存储位置。这个取模操作的目的是将哈希值映射到桶(Bucket)的索引上,桶是 HashMap 中的一个数组,每个桶中会存储着一个链表(或者红黑树),装载哈希值相同的键值对(没有相同哈希值的话就只存储一个键值对)。
总的来说,HashMap 的 hash 方法就是将 key 对象的 hashCode 值进行处理,得到最终的哈希值,并通过一定的算法映射到实际的存储位置上。这个过程决定了 HashMap 内部键值对的查找效率。
蔚来一面:HashMaphash 方法原理是什么?看完这篇还不懂HashMaphash原理,那我要哭了~
沉默王二
09-13 4226
Warning:这是《Java 程序员进阶之路》专栏的第 55 篇。那天,小二去蔚来面试,面试官老王一上来就问他:HashMaphash 方法的原理是什么?当时就把裸面的小二给蚌埠住了。 回来后小二找到了我,于是我就写下了这篇文章丢给他,并严厉地告诉他:再搞不懂就别来找我。听到这句话,心头一阵酸,小二绷不住差点要哭 ????。 PS:本文 GitHub 上已同步,有 GitHub 账号的小伙伴,记得看完后给二哥安排一波 star 呀!冲一波 GitHub 的 trending 榜单,求求各位了。 G
HashMap之get方法详解
热门推荐
weixin_39667787的博客
01-29 3万+
1. 导读 本章节面相的是对红黑树有了解的读者, 因为JAVA引入了黑红树, 所以后面的内容主要围绕着红黑树来展开; .1 get .2 find 2. get HashMap::get返回一个数据节点, 如果不存在则返回空; final Node<K,V> getNode(int hash, Object key) { Node<K,V>[] t...
哈希查找因何快?我们使用它需要付出什么代价
virus026的专栏
01-22 916
 copy from : http://www.cnblogs.com/kwklover/articles/837942.html哈希表和哈希函数是大学数据结构的课程,实际开发我们经常用到Hashtable这种结构,当遇到键-值对存储,采用Hashtable比ArrayList查找的性能高。为什么呢?我们在享受高性能的同时,需要付出什么代价(这几天看红顶商人胡雪岩,经典台词:在你享受这之前
哈希(Hash
最新发布
m0_68224121的博客
08-20 1208
哈希也叫散列,因而哈希表也叫散列表。通过把关键码值映射到表一个位置来访问记录,以加快查找的速度。这个映射函数叫做哈希函数。采用散列函数将记录存储在一块连续的存储空间,这块连续的存储空间称为哈希表。所得的存储地址称为哈希地址。
HASH作用
qq_25174485的博客
03-13 1360
数据经过HASH后,类似加密,其他人就无法看到真实的数据情况,对于敏感明文数据,可以用这种方式保存。同时HASH也可以利用HASH值的唯一性,用于数据查找与分桶。 HASH的构造有多种方法,不变的思想是在现有数据的基础上,通过某种映射函数,把数据变换成另一种形式,数据变换后尽可能不产生冲突,具有唯一性。 如果产生冲突,可以在原有HASH值的基础上再HASH,或者使用2种HASH算法 具体实现的时候,常见的HASH算法有MD5,SHA-1 参考资料: hash算法原理详解_至道-CSDN博客_哈希算
java架构师培训:hash作用
T_LJAVA的博客
01-04 436
一个结构和hash之间有什么关系呢?   实际上,不难猜测,让我们考虑一个场景。假设我们已经有一个哈希表,现在需要存储新数据。上图数组的长度为6,这意味着有6个链接列表可供选择,那么我们应该将这个新元素放入哪个链接列表?    您可能会说,它当然放在了最短的一个,以便可以平衡链表的长度。这真的很好,但是有一个问题。尽管存储起来很方便,但是在阅读时存在很大的问题。因为我们在存储链接列表时知道它存在于最短的链接列表,但是当我们读取它时,我们并不知道哪个链接列表最短,因此很可能已完全更改了整个结构。因此,
哈希(hash)表原理及作用
与其在害怕丢脸,不如在旅途中尽情地丢脸
05-27 7664
哈希表的作用: 优点:(查找速度快) 哈希表是种数据结构,它可以提供快速的插入操作和查找操作。第一次接触哈希表时,它的优点多得让人难以置信。不论哈希表有多少数据,插入和删除(有时包括侧除)只需要接近常量的时间即0(1)的时间级。实际上,这只需要几条机器指令。   对哈希表的使用者一一人来说,这是一瞬间的事。哈希表运算得非常快,在计算机程序,如果需要在一秒种内查找上千条记录通常
javaHashMap详解
07-04
- **构造器**:HashMap提供了多种构造方法,允许用户指定初始容量和负载因子。 - **字段属性**:包括`serialVersionUID`用于序列化一致性,`DEFAULT_INITIAL_CAPACITY`定义了默认初始容量(16),`MAXIMUM_...
HashMap-hash原理
12-26
### HashMapHash原理详解 #### 一、概述 在Java编程语言,`HashMap`是实现`Map`接口的一个常用类,它提供了基于键值对的存储方式,并且允许使用`null`值和`null`键。为了实现高效的数据存取操作,`HashMap`...
Java HashMap 详解
java1527的博客
09-14 2万+
举一个简单的例子,假设我们在目前的平台有键值对 key1-value1,计算出key1的hash为1, 计算后存在table数组下标为1的地方,假设table被序列化了,并传输到了另外的平台,并反序列化为了原来的HashMap,key1-value1仍然存在下标1的位置,当在这个平台运行get("key1")的时候,可能计算出key1的hash为2,就有可能到下标为2的地方去找该元素,这样就出错了。创建新的Node数组,将原来数组的元素重新映射到新的数组。2. 数组的默认长度是16。
HashMap详解
Java框架、并发编程、分布式、微服务、Redis、HarmonyOS、中间件等技术
06-02 2万+
摘要 散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。 HashMapJava程序员使用最频繁的的用于键值对(key value)数据处理的容器,在JDK1.7(Java Developmet Kit)时HashMap采取的是数组+链表的形式存储数据,JDK1.8对HashMap进行了存储结构上的优化,引入了红黑树数.
K:HashMaphash函数的作用
diaosangwan0363的博客
12-11 250
  在分析了hashCode方法和equals方法之后,我们对hashCode方法和equals方法的相关作用有了大致的了解。在通过查看HashMap类的相关源码的时候,发现其存在一个int hash(int h)的方法。在HashMap方法的源码如下: static int hash(int h) { // This function ensures that hashC...
hash算法的作用是什么?
zealot_2002的专栏
11-21 2840
Hash,一般翻译做"散列",也有直接音译为"哈希"的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。 Hash算法在信息安全方面的应用主要体现在以下的3个方面: 1) 文件校验 我们比较熟悉的校
HashMaphash方法
梁诗傑的博客
11-09 882
思路 什么是hash?常见的实现又什么?什么是hash碰撞?怎么衡量一个hash函数的好坏?常见的hash碰撞解决方案有哪些?HashMap or HashTable的hash方法基本原理是什么?jdk7/8HashMap碰撞解决方案的差异?为什么? 概念 任意长度的输入通过散列算法,变换成固定长度的输出,称散列值。 常见的Hash函数 Hash碰撞 不同的输入经过散列算法得到的散列值相同,这种情况称为Hash碰撞。 衡量Hash函数好坏的指标 发生...
HashMaphash方法
Littlemotor
07-06 998
转自:JDK 源码 HashMaphash 方法原理是什么? - 胖君的回答 - 知乎 https://www.zhihu.com/question/20733617/answer/111577937 <div class="RichContent-inner"><span class="RichText ztext CopyrightRichText-richText" itemprop="text">这段代码叫“<b>扰动函数</b>”。&.
字符串hash的用处
Facico的博客
04-28 5231
简介hash(哈希)。 把字符串用一种特定的方式放到一个数组里面。用处我目前学的短,只知道两个用处。1、字符串判重相信很多人都会。2、可以快速判断同一个字符串的两段字符串是否相等maxx=10007; . . . fo(len,1,n)h[len]=h[len-1]*maxx+s[len];//c++可以不用打hash这个十分的爽,因为能自动的弹出一个数(可正可负) fo(len,1,n)g[i
hash算法 (hashmap 实现原理)
htofly的专栏
07-27 605
Hash ,一般翻译做“ 散列” ,也有直接音译为“ 哈希” 的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不 同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。 HAS
Java连载152-HashMaphash函数有什么用
weixin_44630050的博客
12-17 799
一、取模运算和取余运算 取余运算,这个很好理解,我们经过多年的数学学习也知道,就是求余数,一个整数和另一个整数相除,得到它们的余数,就是我们说的取余 取模运算,通俗的来讲大多运算在计算机领域,取模运算其实就是两个二进制数字之间做与运算,它们最后得到的数字就是取模 我们举个简单的例子,有一个二进制数字0000 0001 1001 1101,1111 0101 1010 0011,这个两个数字做与运算,它们相同位置的数字,如果有一个数字出现1,那么计算后的数字的那个位置就是1,这两个数字与运算后的值为1111
关于HashMaphash算法
相忘于江湖
12-21 6206
一、关于Hash表和Hash函数 Hash表也称散列表,直译为哈希表,hash表是一种根据关键字值(key-value)而直接进行访问的数据结构。在哈希表的键值对关系,key到value间还存在着一个映射值,这个映射值就是数组的下标index,key正是通过映射到数组对应的下标index而访问到value值的,但key又是如何映射到数组下标的呢?这就要通过一个映射函数f(key),这个函数我...
写文章

热门文章

  • ElementUI el-input无法输入、修改、删除问题解决 13936
  • Mybatis动态sql 13449
  • java集合转化为数组 10962
  • java数组转换为集合 10192
  • java删除字符串中指定字符 7763

分类专栏

  • Java并发编程 8篇
  • Redis 1篇
  • Java集合 1篇
  • spring进阶 4篇
  • 算法 4篇
  • JVM 6篇
  • 前端学习 1篇
  • mysql进阶 5篇
  • Java进阶 1篇
  • 笔记 5篇

最新评论

  • java集合转化为数组

    半梦=半醒: 写错了,toArray不能强制转换吧

  • Java线程池

    永无魇足: 这篇博客写的太好了,对JAVA的线程池的理解更加深刻了

  • Java线程池

    吃橘子的Crow: 博主写的太好了,自愧不如表情包

  • ThreadLocal内存泄漏问题

    用手写的从前: 表情包

  • ThreadLocal内存泄漏问题

    吃橘子的Crow: 写的真好,内存溢出表情包

大家在看

  • 【快速上手】linux环境下Neo4j的安装与使用
  • 简单生活的快乐 337
  • 黑神话:悟空 后话 189

最新文章

  • Java线程池
  • ThreadLocal内存泄漏问题
  • ThreadLocal(超详细介绍!!)
2023年42篇
2022年42篇
2021年16篇

目录

目录

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值

玻璃钢生产厂家兰州景区玻璃钢雕塑公司深圳玻璃钢字母座椅雕塑玻璃钢卡通雕塑报价单云南玻璃钢卡通雕塑公司仙林商场节庆美陈吉林省玻璃钢雕塑加工绍兴玻璃钢海豚雕塑定制江苏特色玻璃钢雕塑生产厂家玻璃钢假山雕塑厂家成都景区玻璃钢雕塑制作玻璃钢雕塑曲阳厂家拱墅商场美陈福建常用商场美陈厂家直销西湖玻璃钢造型雕塑河南大型商场美陈销售公司江门玻璃钢雕塑费用抚顺市玻璃钢雕塑定制西山区玻璃钢雕塑订制宁夏猪猪侠玻璃钢雕塑厂家商场圣诞节美陈装饰濮阳水景校园玻璃钢雕塑制作松江玻璃钢雕塑制造厂家天水玻璃钢头像雕塑邵阳玻璃钢动物雕塑南充玻璃钢浮雕人物山水雕塑唐山动物玻璃钢雕塑生产厂家哪里做玻璃钢牛头雕塑玻璃钢雕塑喷水玻璃钢卡通座椅雕塑玻璃钢抽象景观雕塑定制香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化