面试逃不过的HashMap哈希原理,这一次一定要弄懂

Java面试要点56 - Java HashMap源码解析:哈希算法 在使用自定义对象作为HashMap的key时,正确实现hashCode()和equals()方法是至关重要的。这两个方法需要满足一致性要求,即相等的对象必须具有相同的哈希码。// 正确实现hashCode()方法@Override// 使用不变的字段计算哈希码// 正确实现equals()方法@Overrideif (!User user1 = new User("1001", "张三");User user2 = new User("1001", "张三"); 阅读详情

1. 前言

HashMap绝对是JDK源码中比较精髓的存在,除此之外还有AQS,线程池等等。但是由于HashMap是我们接触最早也是接触最多的,所以面试八股文中绝对少不了它的存在。

想要学习一门技术能够大概了解它的原理其实已经差不多了,但是面试官往往会刨根问底,追问你put流程,resize过程,为什么负载因子是0.75之类的……

其实这些都还好,最让人头疼的是哈希算法,我们来看看JDK1.8中计算下标的源码:

static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

除此之外还有一句,这个hash就是上面得到的值,而n就是数组长度:

(n - 1) & hash

那么问题来了:

  • 为什么要右移16位?
  • 为什么要和自己再进行异或(^)操作?
  • 为什么要n-1?
  • 为什么是位运算而不是求模?

带着这些疑问,我们继续往下读。

2. 哈希算法的目标

我们都知道HashMap的原理,对于一个key进行哈希运算得到下标,然后把这个key对应的value存入数组中。

我们假设数组容量是16,如果这时候来了一个hashcode是9999的值怎么办?直接用9999做下标会越界,所以我们需要做进一步处理:

保证哈希运算得到的结果在容量范围内。


2.1 如何保证效率?

有人说这还不简单,直接取模不就完事?

hashcode % 16

行了打完收工,我们的哈希算法完事了。如果说这是在你的业务代码里这么写,当然没什么问题。但这可是JDK源码,你业务代码运行的基石,取模运算的本质:

  1. 求整数商:c = a/b;
  2. 计算模/余数:r = a - (c*b);

可以看到,这其中包括了除法、乘法、减法运算,直接取模效率太低了,那么有没有什么方法能够取代求模呢?

当然有:

当length为2的n次方时,其实(length-1)&hashCode计算出来的值和hashCode%length是一致的

于是我们的算法得到了改进:

(length-1)&hashCode

咦?这不就是JDK源码中的(n - 1) & hash吗?除此之外,我们还有个意外收获:HashMap的容量为什么是2的n次幂。


2.2 怎么减少哈希冲突?

效率是提上来了,新的问题又来了:

String a = "张三";
String b = "李四";
String c = "王五";
String d = "赵六";
int length = 31;
System.out.println(a.hashCode() & length);
System.out.println(b.hashCode() & length);
System.out.println(c.hashCode() & length);
System.out.println(d.hashCode() & length);

假设我们有两个hashcode的值a和b,使用我们刚才推导出来的算法,计算出来的下标是这样的:
在这里插入图片描述

可以看到,张三和王五的下标发生了冲突,这个算法的似乎不太聪明的亚子,怎么办?

这个也简单,我们对哈希算法做个扰动即可。

2.3 怎么进行扰动?

事实上,当length=8时,下标运算结果取决于哈希值的低三位,当length=16时,下标运算结果取决于哈希值的低四位,以此类推,我们得出结论:

当length=2的N次方, 下标运算结果取决于哈希值的低N位。

也就是说,我们在进行(n - 1) & hash时,实际上是取低N位的值,那么如何让低N位的值分布得更加均匀呢?

用一个固定的值再去运算一次?这样做太死板了,我们需要的是更加随机,更加均匀。那么我们能不能让它对自己做点手脚?

我们知道,一个hashcode是32位,如果我们对它某些位数的值进行改动,然后再让这个改动后的值与自己进行一次运算,结果是不是就更加随机,更加均匀了?

于是我们可以将高十六位无符号右移之后,与原来的值做异或运算。这样可以让高十六位的特征与低十六位的特征进行了混合,得到的新的数值中就高位与低位的信息都被保留了。

而在这里采用异或运算而不采用& 、| 运算的原因是 异或运算能更好的保留各部分的特征,如果采用&运算计算出来的值会向1靠拢,采用|运算计算出来的值会向0靠拢。

整个过程的核心突出一个点:均匀!

于是我们的算法再次得到了改进:

(hashCode ^ (hashCode >>> 16)) & (length-1)

这不就是JDK源码中的做法吗?

2.4 新的算法效果如何?

我们用刚才推导出来的算法再来运行一次:

String a = "张三";
String b = "李四";
String c = "王五";
String d = "赵六";
int length = 31;
System.out.println(a.hashCode() & length);
System.out.println(b.hashCode() & length);
System.out.println(c.hashCode() & length);
System.out.println(d.hashCode() & length);
System.out.println("--------------------");
System.out.println((a.hashCode() ^ a.hashCode() >>> 16) & length);
System.out.println((b.hashCode() ^ b.hashCode() >>> 16) & length);
System.out.println((c.hashCode() ^ c.hashCode() >>> 16) & length);
System.out.println((d.hashCode() ^ d.hashCode() >>> 16) & length);

结果很明显,计算出来的下标明显均匀了许多!
在这里插入图片描述

3. 结尾

看到这里前面提出的几个问题大家心里应该都有数了,实际上本文还有一些延伸的问题,比如:计算机是怎么进行乘除运算的?为什么位运算可以替代取模?一定要高十六位右移吗?高八位高十二位行不行?

这些问题留给读者去思考,如有问题,欢迎在评论区中留言指正!

面试官:说一下HashMap的实现原理? 哈希表(hash table)也叫散列表,是一种非常重要的数据结构,应用场景及其丰富,许多缓存技术(比如memcached)的核心其实就是在内存中维护一张大的哈希表,而HashMap的实现原理也常常出现在各类的面试题中,重要性可见一斑。 本文会对java集合框架中的对应实现HashMap的实现原理进行讲解,然后会对JDK7的HashMap源码进行分析(JDK8会有所不同,需要了解的可自行阅读JDK8的HashMap源码)。 JDK7和JDK8中HashMap的大致变化是(这其实也是一个常被问道的面试题~ 阅读详情

相关推荐

面试准备——jdk1.7与jdk1.8的HashMap(只重点分析了哈希算法、下标计算、get、put、resize)

写在前面,只是为了面试而准备的笔记,其实之前就有在分析HashMap源码,但是那篇只写了一部分,还躺在草稿箱,不过那篇写的感觉很舒服,等稳定下来想好好写。这篇写的不怎么满意,内容也只有一部分,做个存稿吧。 HashMap 数据结构 jdk1.7 数组 + 链表 jdk1.8 数组 + 链表 + 红黑树 当一个结点的链表长度大于8时,链表会转换成红黑树,提高查询效率,而链表长度小于6时又会退化成链表...

weixin_42907817的博客 4230

JDK1.8中HashMap如何应对hash冲突?

1 什么是hash冲突 我们知道HashMap底层是由数组+链表/红黑树构成的, 当我们通过put(key, value)向hashmap中添加元素时,需要通过散列函数确定元素究竟应该放置在数组中的哪个位置,当不同的元素被放置在了数据的同一个位置时,后放入的元素会以链表的形式,插在前一个元素的尾部,这个时候我们称发生了hash冲突。 2 如何解决hash冲突 事实上,想让hash冲突完全不发生,是...

Desperdo 1万+

蔚来一面:HashMap 的 hash 方法原理是什么?看完这篇还不懂HashMap的hash原理,那我要哭了~

Warning:这是《Java 程序员进阶之路》专栏的第 55 篇。那天,小二去蔚来面试,面试官老王一上来就问他:HashMap 的 hash 方法的原理是什么?当时就把裸面的小二给蚌埠住了。 回来后小二找到了我,于是我就写下了这篇文章丢给他,并严厉地告诉他:再搞不懂就别来找我。听到这句话,心头一阵酸,小二绷不住差点要哭 ????。 PS:本文 GitHub 上已同步,有 GitHub 账号的小伙伴,记得看完后给二哥安排一波 star 呀!冲一波 GitHub 的 trending 榜单,求求各位了。 G

沉默王二 4517

HashMap如何解决哈希冲突?

1. Hash算法和Hash表 了解Hash冲突首先了解Hash算法和Hash表 Hash算法就是把任意长度的输入通过散列算法变成固定长度的输出,这个输出结果就是一个散列值 Hash表又叫做“散列表”,它是通过key直接访问到内存存储位置的数据结构,在具体的实现上,我们通过Hash函数,把key映射到表中的某个位置,来获取这个位置的数据,从而加快数据的查找 2. Hash冲突 Hash冲突是由于哈希算法,被计算的数据是无限的,而计算后的结果的范围是有限的,总会存在不同的数据,经过计算之后得到值是一样,

huangqingfeng的博客 2万+

一分钟教会你搭建steam新游幻兽帕鲁服务器

总结: 游戏对服务器搭建要求相对较高、且对服务器网络协议有要求不能封堵UDP、多开、游戏运行久、同时在线人数多了这些会很吃内存 我自己用的64G内存多开4区测试玩家同时在线50多人的情况下内存已经跑满了、对于想用服务器搭建联机的小伙伴建议根据开区数量以及玩家人数去选择配置、当然也可以直接找我阿杰购买、我可以提供技术搭建服务。注:如果用的是本地电脑局域网搭建直接输入127.0.0.1:8211就行 如果用的是服务器搭建输入自己服务器IP+端口或解析的域名+端口进入游戏。

用最简单的方式说最重要的事!服务器、存储、云计 算、A智能的大数据产品、游戏开发技术。致力于广 大开发者、政企用户、各项机构等,构建云上世界提供全方位云计算解决方案。旨在打造差异化的开放式闭环生态系统帮助用户快速构建稳定、安全的云计算环境。 2236

【库卡机器人】接线步骤

准备X11插头接线,X11插头可以接入机器人外部安全回路接线,其中外部使能信号线也接在此接口上,如果机器人系统没有配置外部使能装置,那个此接口上的外部使能信号端须短接,短接规则为:20-21、23-22、31-30、33-32。持续按住使能键,保持使能上电状态,分别按住示教器右侧每个轴对应的+或-按键,测试机器人每一个轴是否能正常运行,如果一切正常,说明机器人控制正常,机器人可以正常使用。将一根黄绿色等电位线接入其中的一个接地端,并与机器人的接地端相连,使得控制柜与机器人等电位。

qq_45161762的博客 9441

HashMap 怎样解决hash冲突?

HashMap冲突解决方法比较考验一个开发者解决问题的能力。 下文给出HashMap冲突的解决方法以及原理分析,无论是在面试问答或者实际使用中,应该都会有所帮助。 在Java编程语言中,最基本的结构就是两种,一种是数组,一种是模拟指针(引用),所有的数据结构都可以用这两个基本结构构造,HashMap也一样。 当程序试图将多个 key-value 放入 HashMap 中时,以如下代码片段为例: HashMap<String,Object>m=newHashMap<String,O

天道酬勤 906

【军标】《军用软件计价规范(试行)》和GJB 10162-2021《军用软件计价功能项识别方法》-费用标准解读系列37

2021年2月1日实施的《军用软件计价规范(试行)》(替代了2019年版本)以及2021年3月1日实施的《军用软件计价功能项识别方法》(GJB 10162-2021),是我们平时在军用软件造价咨询中进行软件规模度量、计价和审价的主要依据。《军用软件计价规范(试行)》(4号文)的附件1为《军用软件功能规模度量方法》,即4号文本身包含对软件规模测试的方法(功能点方法主要参考NESMA等国际标准)、规模度量过程、功能点计数和计算规则等相关说明。(四)软件研发费用=软件研发工作量x软件研发人月综合费率。

xiaosenyouli的博客 6129

关于HashMap中的hash算法

一、关于Hash表和Hash函数 Hash表也称散列表,直译为哈希表,hash表是一种根据关键字值(key-value)而直接进行访问的数据结构。在哈希表的键值对关系中,key到value中间还存在着一个映射值,这个映射值就是数组的下标index,key正是通过映射到数组对应的下标index而访问到value值的,但key又是如何映射到数组下标的呢?这就要通过一个映射函数f(key),这个函数我...

相忘于江湖 6444

【Python基础】FastAPI 从入门到项目实战操作详解

【Python基础】FastAPI从入门到使用实战操作详解

congge_study的博客 449

银行统一监管报送系统

依据《银行业金融机构数据治理指引》,银行业金融机构应当建立适应监管数据报送工作需要的信息系统,实现流程控制的程序化,提高监管数据加工的自动化程度。银行业金融机构应当将监管数据纳入数据治理,建立工作机制和流程,确保监管数据报送工作有效组织开展,监管数据质量持续提升。银行通常要对接报送EAST5.0、1104、CRSS等近40个监管应用,涉及近1000张报表。表13-01是主要的监管报送应用、报送依据、报送规范、监管机构名称。

银行信息系统应用架构详解 4350

HashMap之Hash解读

HashMap基础源码阅读 最近又看了一下hashMap的源码,发现了一些之前没有关注到的内容,比如Hash为什么要这么设计?后续的很多功能都会基于这个Hash算法进行延伸,比如扩容等等,今天重新再来认识一遍hash的算法。 首先展示代码: // 构建hash static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); } //

长沙要起风了、 573

流体动力学仿真软件:Star-CCM+_(1).Star-CCM+基础及入门

Star-CCM+的用户界面(UI)分为多个部分,包括菜单栏、工具栏、工作区、视图窗口和控制台。菜单栏包含文件、编辑、视图、工具等常用菜单。例如,“File”菜单可以用于打开、保存和退出项目。工具栏提供常用的工具按钮,如新建项目、打开项目、保存项目等。也可以自定义工具栏,添加常用的功能按钮。工作区显示当前项目的结构和各个对象。可以通过拖拽方式组织和管理项目中的各个部分。视图窗口显示几何模型、网格、结果等。可以通过不同的视图模式查看和分析数据。控制台显示软件的运行日志和输出信息。

kkchenjj的博客 1202

搞定leetcode面试经典150题之哈希算法

HashSet:是一个不允许重复元素的集合,它基于HashMap来实现,add()方法通过计算元素的哈希值来确定存储位置,避免元素重复。HashMap:是一个键值对集合,put()方法通过计算键的哈希值来确定存储位置,并将对应的值存储到该位置。哈希函数:哈希表的效率依赖于哈希函数的质量,优秀的哈希函数可以减少哈希冲突,提高操作效率。

buyaotutou的博客 1857

脉冲变压器电感选型参数,结构原理,工艺与注意问题总结

脉冲变压器电感简称脉冲变压器,是一种特殊类型的变压器,主要用于处理脉冲信号。它的主要特性是能够在短时间内承受高电压和大电流。脉冲变压器主要用于开关电源、脉冲功率放大、雷达脉冲调制等领域。本文对脉冲变压器的工作原理,结构特点,工艺流程,选型参数及设计注意事项进行总结。

fydar的博客 1347

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

HashMap底层实现原理

HashMap底层实现原理 HashMap是Java语言中用的最频繁的一种数据结构。 1.hashmap的数据结构 要了解hashmap首先要弄清楚他的结构。在java编程语言中最基本的数据结构有两种,数组和链表。 数组:查询速度快,可以根据索引查询;但插入和删除比较困难; 链表:查询速度慢,需要遍历整个链表,但插入和删除操作比较容易。 hashmap是数组和链表组成的,数据结构中又叫“链表散列”...

kun_998的博客 6万+

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

HashMap底层原理剖析(面试收藏!!!)

HashMapHashMap底层原理剖析(超详细!!!)一、散列表结构二、什么是哈希?三、HashMap原理讲解3.1继承体系图3.2Node数据结构分析3.3底层存储结构3.4put数据原理分析3.5什么是哈希碰撞?3.6JDK8为什么引入红黑树?3.7扩容机制四、手撕源码1.HashMap核心属性分析2.构造方法分析3.put方法分析4.resize()方法分析5.get方法6.remove方法分析7.replace方法分析 HashMap底层原理剖析(超详细!!!) 一、散列表结构 散列表结构就是数组

zjdzka的博客 1万+

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

HashMap底层实现原理及面试问题

一、HashMap的工作原理 HashMap基于hashing原理,我们通过put()和get()方法储存和获取对象。当我们将键值对传递给put()方法时,它调用键对象的hashCode()方法来计算hashcode,让后找到bucket位置来储存值对象。当获取对象时,通过键对象的equals()方法找到正确的键值对,然后返回值对象。HashMap使用链表来解决碰撞问题,当发生碰撞了,对象将会储存在链表的下一个节点中。 HashMap在每个链表节点中储存键值对对象。 当两个不同的键对象的hashcode

学Java,找哪吒 1万+

hashmap hash冲突怎么解决_HashMap原理

HashMap的问题,在现在的技术面试中,基本上都会问到,而且这个集合在开发中也会经常使用到,希望通过本文能有所收获。一、问题分析1、HashMap的底层数据结构是什么?2、HashMap中CRUD操作的底层实现原理是什么?3、HashMap是如何实现扩容的?4、HashMap的hash冲突是怎样解决的?5、HashMap为什么线程不安全?二、认识HashMapHashMap最早出现在jdk1.2...

weixin_42398171的博客 5193

什么是哈希算法?(大白话+原理+应用,一次讲透)

哈希算法摘要:哈希算法将任意输入转换为固定长度的哈希值,具有确定性、单向性和抗碰撞性。核心原理是通过计算直接定位存储位置,使 HashSet 的查找操作达到 O(1) 时间复杂度,远优于 List 的 O(n) 遍历。其应用包括数据结构优化(如 HashSet)、密码存储、文件校验和区块链等。哈希碰撞通过链地址法或红黑树解决。在算法优化中(如滑动窗口问题),哈希算法通过快速定位显著提升性能。

weixin_45784564的博客 1245

Java面试宝典:HashMap底层原理

HashMap 基于数组+链表/红黑树实现,通过哈希函数(扰动高位优化分布)计算键的索引位置,用链表解决哈希冲突(Java 8 后链表超8转红黑树优化查询效率),动态扩容时容量翻倍并重哈希(负载因子默认0.75),非线程安全(多线程推荐 ConcurrentHashMap)。其设计核心是空间换时间,通过高效哈希计算、冲突管理和扩容策略实现 O(1) 平均操作复杂度,需注意键对象的 hashCode() 和 equals() 正确实现以保障性能。

笃行其道的博客 2181

Java HashMap面试攻略:从菜鸟到高手的进阶之路

Java HashMap面试攻略:从底层原理到高级技巧 本文系统解析Java HashMap核心知识点,帮助开发者从入门到精通。主要内容包括: 数据结构演进:JDK1.7的数组+链表升级为1.8的数组+链表+红黑树 哈希算法精妙设计:高低位异或的扰动函数优化 容量设计的数学原理:2的n次方长度确保高效位运算和均匀分布 红黑树选择原因:内存友好性优于B树和AVL树 扩容机制优化:JDK1.8的位运算定位新位置 线程安全方案对比:Hashtable、Collections.synchronizedMap和Con

weixin_54726354的博客 987

Java HashMap源码分析、hash 原理、扩容机制、加载因子、线程不安全

上一个问题提到了加载因子(或者叫负载因子),那么这个问题我们来讨论为什么加载因子是 0.75 而不是 0.6、0.8。我们知道,HashMap 是用数组+链表/红黑树实现的,我们要想往 HashMap 中添加数据(元素/键值对)或者取数据,就需要确定数据在数组中的下标(索引)。int h;数组的容量过小,经过哈希计算后的下标,容易出现冲突;数组的容量过大,导致空间利用率不高。加载因子是用来表示 HashMap 中数据的填满程度:加载因子 = 填入哈希表中的数据个数 / 哈希表的长度。

wswpomos的博客 4827

HashMap图解原理与数据结构

面试被虐周末你好!我是狮子王辛巴。一名无缘985,日常996工程师。利用周末休息时间给大家献上一篇技术文章。作为一名为人民币服务的工程师,学好技术是多么重要的事情。今天跟各位老铁们详细说...

weixin_43167418的博客 3218

Hash算法、Hash函数、Hash表、HashMap的区别联系和详细解释(数据结构考研,哈希算法,哈希函数,哈希表,哈希Map)

一、问题背景 博主最近在了解并使用Java中的HashMap,但是博主发现若博主不彻底弄懂Hash算法、Hash函数、Hash表、HashMap之间的区别与联系,博主将无法准确地理解Java的HashMap,因此博主浏览了相关文章,做出了以下总结。 本文参考文献: [1]哈希表、Java中HashMap [2]哈希表(散列表)原理详解 [3]Java HashMap原理详解 [4]Java基础之H...

快乐李同学的博客 944
上一篇: 为什么有MESI了还要volatile?你真的了解volatile吗
下一篇: 关于while与println的现象,你还在认为是println方法有synchronized修饰吗?
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值