HashMap就是这么简单【源码剖析】

【Java集合源码剖析】HashMap源码剖析 HashMap简介 HashMap是基于哈希表实现的,每一个元素是一个key-value对,其内部通过单链表解决冲突问题,容量不足(超过了阀值)时,同样会自动增长。 HashMap是非线程安全的,只是用于单线程环境下,多线程环境下可以采用concurrent并发包下的concurrentHashMap。 HashMap 实现了Serializable接口,因此它支持序列化,实现了Cloneable接口,能被克隆。 阅读详情

前言

声明,本文用得是jdk1.8

前面已经讲了Collection的总览和剖析List集合以及散列表、Map集合、红黑树的基础了:

本篇主要讲解HashMap,以及涉及到一些与hashtable的比较~

看这篇文章之前最好是有点数据结构的基础:

当然了,如果讲得有错的地方还请大家多多包涵并不吝在评论去指正~

一、HashMap剖析

首先看看HashMap的顶部注释说了些什么:

再来看看HashMap的类继承图:

下面我们来看一下HashMap的属性:

成员属性有这么几个:

再来看一下hashMap的一个内部类Node:

我们知道Hash的底层是散列表,而在Java中散列表的实现是通过数组+链表的~

再来简单看看put方法就可以印证我们的说法了:数组+链表–>散列表

我们可以简单总结出HashMap:

  • 无序,允许为null,非同步
  • 底层由散列表(哈希表)实现
  • 初始容量和装载因子对HashMap影响挺大的,设置小了不好,设置大了也不好

1.1HashMap构造方法

HashMap的构造方法有4个:

在上面的构造方法最后一行,我们会发现调用了tableSizeFor(),我们进去看看:

这是位运算算法,具体流程可参考:

看完上面可能会感到奇怪的是:为啥是将2的整数幂的数赋给threshold?

  • threshold这个成员变量是阈值,决定了是否要将散列表再散列。它的值应该是:capacity * load factor才对的。

其实这里仅仅是一个初始化,当创建哈希表的时候,它会重新赋值的:

至于别的构造方法都差不多,这里我就不细讲了:

1.2put方法

put方法可以说是HashMap的核心,我们来看看:

我们来看看它是怎么计算哈希值的:

为什么要这样干呢??我们一般来说直接将key作为哈希值不就好了吗,做异或运算是干嘛用的??

我们看下来:

我们是根据key的哈希值来保存在散列表中的,我们表默认的初始容量是16,要放到散列表中,就是0-15的位置上。也就是tab[i = (n - 1) & hash]。可以发现的是:在做&运算的时候,仅仅是后4位有效~那如果我们key的哈希值高位变化很大,低位变化很小。直接拿过去做&运算,这就会导致计算出来的Hash值相同的很多。

而设计者将key的哈希值的高位也做了运算(与高16位做异或运算,使得在做&运算时,此时的低位实际上是高位与低位的结合),这就增加了随机性,减少了碰撞冲突的可能性!

下面我们再来看看流程是怎么样的:

新值覆盖旧值,返回旧值测试:

接下来我们看看resize()方法,在初始化的时候要调用这个方法,当散列表元素大于capacity * load factor的时候也是调用resize()

1.3get方法

接下来我们看看getNode()是怎么实现的:

1.4remove方法

再来看看removeNode()的实现:

二、HashMap与Hashtable对比

从存储结构和实现来讲基本上都是相同的。它和HashMap的最大的不同是它是线程安全的,另外它不允许key和value为null。Hashtable是个过时的集合类,不建议在新代码中使用,不需要线程安全的场合可以用HashMap替换,需要线程安全的场合可以用ConcurrentHashMap替换

Hashtable具体阅读源码可参考:

四、总结

在JDK8中HashMap的底层是:数组+链表(散列表)+红黑树

在散列表中有装载因子这么一个属性,当装载因子*初始容量小于散列表元素时,该散列表会再散列,扩容2倍!

装载因子的默认值是0.75,无论是初始大了还是初始小了对我们HashMap的性能都不好

  • 装载因子初始值大了,可以减少散列表再散列(扩容的次数),但同时会导致散列冲突的可能性变大(散列冲突也是耗性能的一个操作,要得操作链表(红黑树)!
  • 装载因子初始值小了,可以减小散列冲突的可能性,但同时扩容的次数可能就会变多!

初始容量的默认值是16,它也一样,无论初始大了还是小了,对我们的HashMap都是有影响的:

  • 初始容量过大,那么遍历时我们的速度就会受影响~
  • 初始容量过小,散列表再散列(扩容的次数)可能就变得多,扩容也是一件非常耗费性能的一件事~

从源码上我们可以发现:HashMap并不是直接拿key的哈希值来用的,它会将key的哈希值的高16位进行异或操作,使得我们将元素放入哈希表的时候增加了一定的随机性。

还要值得注意的是:并不是桶子上有8位元素的时候它就能变成红黑树,它得同时满足我们的散列表容量大于64才行的~


明天要是无意外的话,可能会写TreeMap,敬请期待哦~~~~

文章的目录导航:https://zhongfucheng.bitcron.com/post/shou-ji/gong-zhong-hao-wen-zhang-zheng-li

如果文章有错的地方欢迎指正,大家互相交流。习惯在微信看技术文章,想要获取更多的Java资源的同学,可以关注微信公众号:Java3y。为了大家方便,刚新建了一下qq群:742919422,大家也可以去交流交流。
谢谢支持了!希望能多介绍给其他有需要的朋友

参考资料:

python3.12 在用django5.0创建超级用户时,遇到AttributeError: module ‘hashlib‘ has no attribute ‘pbkdf2_hmac‘的问题 产生问题的原因是python3.12的hashlib没有自带pbkdf2_hmac函数,该函数是加密算法的一种,只要通过别的函数导入pbkdf2_hmac即可。还有一种方法是将django默认使用的pbkdf2_hmac改为hashlib自带的sha2或其他算法返回加密的密码,笔者以后会尝试用此类办法解决问题。2.找到报错文件的位置/usr/local/lib/python3.12/site-packages/django/utils/crypto.py。保存修改的文件,重新执行创建超级用户的命令成功。 阅读详情

相关推荐

【Blockly开发教程】01 初识Blockly

Blockly 是由 Google 开发的开源代码库,它可以为网页程序和移动端应用程序添加可视化代码编辑器。

Bright的博客 4512

JAVA | Collection集合 之 HashMap

HashMap 数据结构 1.7=< 数组+链表 =>1.8 数组+链表+红黑树 重要的变量 1.8版本 /** * 默认初始容量,2的4次方 = 16 */ static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; /** * 最大容量2的30次方, 并且容量必须是2的幂 */ static final int MAXIMUM_CAPACITY = 1 &lt

子墨将的博客 419

Keil5 安装与卸载全攻略:从零开始到完美避坑

本文提供了Keil5集成开发环境的完整安装与卸载指南。针对嵌入式开发新手,详细解析了安装前的关键准备、MDK核心与C51双环境的安装激活步骤、常见问题排查,并重点介绍了如何彻底卸载软件以避免残留问题,帮助用户从零开始搭建稳定高效的开发环境。

weixin_29172963的博客 636

深入Collection之HashMap

深入Collection之HashMap作为Map中最常使用的实现类HashMap,它的重要性当然毋庸置疑,所以这篇文章就是有关HashMap的实现和功能介绍。 成员变量 //默认数组初始化容量 static final int DEFAULT_INITIAL_CAPACITY = 16; /** * 定义最大的数组容量,当初始化时的入参的capacity容量比这个值大

paditang的博客 2150

大学生电赛学习之路

可以看到全国大学生电子设计大赛的认可度是非常高的,属于A类学科竞赛。电子设计大赛的形式也是给出题目,参赛者有四天三夜的时间解决问题,题目大致可以分为:控制类、测量类、高频类以及电力电子类。该竞赛会在单数年的9月份举行。但是对于新生来说电赛确实遥不可及的,可能在很多学校本科生是不能进入实验室的,但是就算进了实验室你就有资格去参加电赛或者说能拿一个不错的奖项吗? 现在正值新生开学季,当然会有一大批学生会进入实验室的学习,电赛的举办时间是每年的暑假,所以说对于大一同学来说有一年的时间去准备,那我们就来说一说参加.

weixin_46098612的博客 8789

XC7Z010-1CLG400C开发板ADC引脚配置全攻略(附完整引脚列表)

本文详细解析了XC7Z010-1CLG400C开发板的ADC引脚配置方法,涵盖XADC模块基础、CLG400封装的引脚布局、硬件设计规范及Vivado工程配置实战。特别提供了完整的引脚列表和性能优化技巧,帮助开发者高效实现模拟信号采集,适用于Zynq-7000系列开发。

weixin_29188043的博客 466

Java 集合Collection—Map

HashMap,key 唯一、value 可重复、允许 null key/value,,增删查平均。

luck_xiang的博客 820

Vue - 详细完美解决 ElementUI MessageBox “多次“ 弹框问题,让其无论执行多少次都只弹出来一次(常见于请求拦截器多次触发弹框,导致弹出来很多个)详细示例代码,保证完美解决!

vue如何防止ElementUIMessageBox多次弹框,vueelement弹框弹出来很多次怎么办,elementvueMessageBox解决执行多次后出现多次弹框的问题,elementUI如何阻止MessageBox多次弹出来,vue+element解决多个请求同时报错,弹出多个消息框message,饿了么组件库MessageBox弹框频繁弹出解决方法,vue调用MessageBox出现多次弹框,vueelementMessageBox怎么只弹出一次,vue之axios请求

🏆 前端领域优质创作者 8196

【Java集合】Collection Map接口,HashMap底层,HashTable,LinkedList,LinkedHashSet,LinkedHashMap等

Java集合一、java集合二、Collection接口1.List接口1.ArrayList2.LinkedList3.Vector4.以上三者异同,ArrayList扩容机制2.Set接口1.HashSet重写hashCode原则重写equals原则2.LinkedHashSet3.TreeSet三、Map接口1.HashMap2.LinkedHashMap3.TreeMap4.HashTable5.Properties四、Collections工具类知识图谱 一、java集合 Java集合可分为Col

A-Itfuture的博客 685

LeRobot 官方论文:一个用于端到端机器人学习的开源库

本文介绍了一个名为LeRobot的开源库,旨在解决机器人学习领域的碎片化问题。该库提供了端到端的技术栈,包括统一的机器人中间件API、标准化的数据集格式(LeRobotDataset)、优化的推理栈以及多种最先进机器人学习算法的实现。LeRobot支持多种低成本开源机器人平台(如SO-10X、ALOHA-2等),通过共享中间件实现便捷的遥操作和数据收集。其数据集格式已广泛应用于社区,截至2025年9月已有16,000多个数据集公开共享。该库还支持流式处理大规模数据,降低了研究门槛。在模型方面,LeRobot

2506_90492529的博客 906

人工智能智能体研究综述:从理论架构到前沿应用

AI Agent,即人工智能智能体,是指能够在特定环境中自主感知、推理、决策并执行行动以实现特定目标的智能系统[1]。自主性反应性主动性(Pro-activeness)和社会性fill:#333;important;important;fill:none;color:#333;color:#333;important;fill:none;fill:#333;height:1em;AI Agent核心特征自主性 Autonomy反应性 Reactivity主动性 Pro-activeness。

nmdbbzcl的博客 902

hashmap是散列表吗_图文剖析HashMap源码,就是这么简单!

作者 |Java3y来源 | Java3y一、HashMap剖析首先看看HashMap的顶部注释说了些什么:再来看看HashMap的类继承图:下面我们来看一下HashMap的属性:成员属性有这么几个:再来看一下hashMap的一个内部类Node:我们知道Hash的底层是散列表,而在Java中散列表的实现是通过数组+链表的~再来简单看看put方法就可以印证我们的说法了:数组+链表--...

weixin_32064437的博客 196

S7-200SMART 的运动控制(一)向导配置具体步骤(图文)

S7-200SMART 的运动控制(一)向导配置具体步骤(图文)

Robot_PLC_HMI_Automation 3850

JDK1.8HashMap源码的简单剖析(1)

HashMap源码的剖析 最近大家都在找实习,而对于Java方向的同学,面试最常问的也是Java集合中的Map,Map有那几种,每种的简单实现都是什么,每种的使用场景都是什么。 昨天去面试,结果被问到,面试官一般问的都是HashMap的原理,是怎么实现的,然后里面重要的几个方法都是怎么实现的。然后如果让你实现一个HashMap,你会怎么实现。 在了解HashMap之前,先理解一下哈希表。

wf_learner的博客 538

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

HashMap的这个小“坑”;老司机也容易翻车

每一种数据结构,都有他其独有的特性;因此,基础知识的部分,一定要将差异部分的原理了解清楚,只要这样,在遇到问题的时候,才能准确分析出问题的本质,否则很容易被表象,被日志给迷惑而陷入迷茫;好了,今天的分享就到这里,不介意的话,三连给安排一下!感激不尽!

Java_fenxiang的博客 728

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

LinkedHashMap与HashMap 关系

LinkedHashMap源码分析 1. LinkedHashMap 与 HashMap 的关系 2. LinkedHashMap 双向链表的构建过程 3. LinkedHashMap 删除节点的过程 4. LinkedHashMap 如何维持访问顺序 5. LinkedHashMap - LRU (Least Recently Used) 最简单的构建方式 LinkedHashMap 与 Ha...

LH197318的博客 399

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

搞懂 Java LinkedHashMap 源码

LinkedHashMap 源码分析 上周学习了 HashMap 的源码感觉收获颇多,虽然红黑树这个坑自己还没有填,但是我没脸没皮的先看了 LinkedHashMap 的源码。因为LinkedHashMap的确跟HashMap有很大关系,看完这篇文章相信大家也会有这种感觉。由于有了 HashMap 源码的分析铺垫,这篇文章我们将从以下几个方面来分析 LinkedHashMap的源码: ...

王小六的博客 817

HashMap原理底层剖析

注意以下文章可能有描述和理解上的错误,如果出现错误请到评论区指出,我会第一时间修改问题。也希望文章能解决你的疑惑。 HashMap结构图 HashMap底层数据结构:Entry数组+链表+红黑树(JDK1.8版本) Entry+链表(JDK1.7版本) ...

weixin_44048140的博客 7587

【源码解读系列六】深入剖析HashMap的底层源码

这篇文章对HashMap的源码进行了解析,希望对你的学习及其面试有所帮助!

扬帆向海的博客 1万+

【java集合框架源码剖析系列】java源码剖析之HashMap

前言:之所以打算写java集合框架源码剖析系列博客是因为自己反思了一下阿里内推一面的失败(估计没过,因为写此博客已距阿里巴巴一面一个星期),当时面试完之后感觉自己回答的挺好的,而且据面试官最后说的这几天可能会和你联系来看当时以为自己一面应该是通过的,但是事与愿违,痛定思痛,仔细回顾了一下面试官问我的整个过程,感兴趣的可以参看我的博客:【阿里内推一面】记我人生的处女面。感觉自己回答的不是很好的地方就

(* ̄︶ ̄) 1万+

剖析HashMap源码

今天就来好好剖析一下HashMap的源码吧~ 不说废话,直接上源码 先说一下参数 Node&lt;K,V&gt;[] table:真正储存键值对 static final int DEFAULT_INITIAL_CAPACITY = 1 &lt;&lt; 4;//初始化容量为16(桶的数量) static final int MAXIMUM_CAPACITY = 1 &...

bingoxin的博客 209

HashMap源码解析【原来这么简单】

数组+链表(散列表)+红黑树在散列表中有装载因子这么一个属性,当装载因子*初始容量小于散列表元素时,该散列表会再散列,扩容2倍!装载因子的默认值是0.75,无论是初始大了还是初始小了对我们HashMap的性能都不好装载因子初始值大了,可以减少散列表再散列(扩容的次数),但同时会导致散列冲突的可能性变大(散列冲突也是耗性能的一个操作,要得操作链表(红黑树)!装载因子初始值小了,可以减小散列冲突的可能性,但同时扩容的次数可能就会变多!初始容量的默认值是16初始容量过大,那么遍历时我们的速度就会受影响~

风一样 979
上一篇: Map集合、散列表、红黑树介绍
下一篇: LinkedHashMap就这么简单【源码剖析】
Java3y
Java3y 领域专家: 后端开发技术领域 领域专家: 后端开发技术领域
博客等级 码龄9年 1万+粉丝 509原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值