HashMap底层的实现原理

news2024/11/17 13:37:56

目录

    • 一、知识点回顾
    • 二、HashMap 的 put() 和 get() 的实现
      • 2.1 map.put(k, v) 实现原理
      • 2.2 map.get(k) 实现原理
      • 2.3 为何随机增删、查询效率都很高?
      • 2.4 为什么放在 HashMap 集合 key 部分的元素需要重写 equals 方法?
      • 2.5 HashMap总结
      • 2.6 JDK8 之后,HashMap的改变
      • 2.7 HashMap 的哈希碰撞
      • 2.8 HashMap 的 key 允许为 null 吗?

HashMap的底层是通过数组 + 单向链表/红黑树实现的。

一、知识点回顾

数组特点:

  • 存储区间是连续的,且占用内存严重,空间复杂度也很大,时间复杂度为 O(1)。
  • 优点: 随机读取效率很高,原因是数组是连续的(随机访问性强,查找速度快)。
  • 缺点: 插入和删除数据效率低,因插入数据,这个位置后面的数据在内存中要后移,且大小固定不易动态扩展。

链表特点:

  • 区间离散,占用内存宽松,空间复杂度小,时间复杂度 O(n)。
  • 优点: 插入删除速度快,内存利用率高,没有大小固定,扩展灵活。
  • 缺点: 不能随机查找,每次都是从第一个开始遍历(查询效率低)。

哈希表特点:

以上数组和链表,大家都知道各自优缺点。那么我们能不能把以上两种结合在一起使用,从而实现查询效率高和删除插入效率也高的数据结构呢?答案是可以滴,那就是哈希表可以满足,接下来我们一起复习下 HashMap 中的 put() 和 get() 方法实现原理。

二、HashMap 的 put() 和 get() 的实现

2.1 map.put(k, v) 实现原理

  • 第1步,首先将 k, v 封装到 Node 对象当中(节点)。

  • 第2步,它的底层会调用 K 的 hashCode() 方法得出 hash 值。

  • 第3步,通过哈希表函数/哈希算法,将 hash 值转换成数组的下标:

    • 下标位置上如果没有任何元素,就把 Node 添加到这个位置上;
    • 如果说下标对应的位置上有链表,就会拿着 k 和链表上每个节点的 k 进行 equals:
      • 如果所有的 equals 方法返回都是 false,那么这个新的节点将被添加到链表的末尾;
      • 如其中有一个 equals 返回了 true,那么这个节点的 value 将会被覆盖。

在这里插入图片描述

2.2 map.get(k) 实现原理

  • 第1步,先调用 k 的 hashCode() 方法得出哈希值,并通过哈希算法转换成数组的下标。
  • 第2步,通过上一步哈希算法转换成数组的下标之后,再通过数组下标快速定位到链表所在位置上。
    • 如果这个位置上什么都没有,则返回 null;
    • 如果这个位置上有单向链表,那么它就会拿着参数 k 和单向链表上的每一个节点的 k 进行 equals:
      • 如果所有 equals 方法都返回 false,则 get 方法返回 null;
      • 如果其中一个节点的 k 和参数 k 进行 equals 返回 true,那么此时该节点的 value 就是我们要找的 value 了,get 方法最终返回这个要找的 value。

在这里插入图片描述

2.3 为何随机增删、查询效率都很高?

原因: 增删是在链表上完成的,而查询主要是通过数组定位,然后扫描部分链表,所以效率高。

HashMap 集合的 key,会先后调用两个方法:hashCode() 和 equals() 方法,所以当对象充当 key 时,这两个方法都需要重写。

2.4 为什么放在 HashMap 集合 key 部分的元素需要重写 equals 方法?

原因: 因为 equals 默认比较的是两个对象的内存地址,如果想根据对象的属性来判断,则需要重写。

2.5 HashMap总结

问题1: HashMap 的 key 为什么是无序的?
答: 因为不一定挂到哪一个单向链表上,因此加入顺序和取出也不一样。

问题2: HashMap 怎么保持不可重复?
答: 使用 equals 方法来保证 HashMap 的 key 不可重复。如果 key 重复的话,value 就会覆盖。存放在 HashMap 集合中的 key,其实就是存放在 HashSet 集合中,所以 HashSet 集合也需要重写 equals() 和 hashCode() 方法。

问题3: HashMap 是如何扩容的?
答: HashMap 集合的默认初始化容量为16,默认加载因子为 0.75,也就是说当 HashMap 集合底层数组的容量达到 75% 时,数组就开始扩容。HashMap 集合初始化容量是 2 的倍数,是为了达到散列均匀,提高 HashMap 集合的存取效率。

2.6 JDK8 之后,HashMap的改变

JDK8 之后,如果哈希表单向链表中元素超过 8 个,那么单向链表这种数据结构会变成红黑树数据结构。当红黑树上的节点数量小于 6 个,会重新把红黑树变成单向链表数据结构。

2.7 HashMap 的哈希碰撞

如果 key1 和 key2 的哈希值相同,就会存放到同一个单向链表上。

如果 key1 和 key2 的哈希值不同,但由于哈希算法执行结束之后转换的数组下标可能相同,此时会发生哈希碰撞

2.8 HashMap 的 key 允许为 null 吗?

允许

JDK8 中 HashMap 的 put() 方法:

public V put(K key, V value) {
    // 采用 hash(key) 来计算 key 的 hashCode 值
    return putVal(hash(key), key, value, false, true);
}

static final int hash(Object key) {
    int h;
    // 当 key 为 null 的时候,不走 hashCode() 方法
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

HashMap 中使用 hash() 方法来计算 key 的哈希值,当 key 为 null 时,直接令 key 的哈希值为0,不走 key.hashCode() 方法,所以即使为 null 也不会抛出空指针异常。

整理完毕,完结撒花~ 🌻





参考地址:

1.来复习一波,HashMap底层实现原理解析,https://baijiahao.baidu.com/s?id=1665667572592680093&wfr=spider&for=pc

2.java中的hashMap允许key为null的原因,https://blog.csdn.net/weixin_46984636/article/details/120606095

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/390473.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

由点到面贯穿整个Java泛型理解

泛型概述 Java泛型(generics)是DK5中引入的一个新特性,泛型提供了编译时类型安全监测机制,该机制允许我们在编译时检测到非法的类型数据结构。 泛型的本质就是参数化类型,也就是所操作的数据类型被指定为一个参数。 如我们经常使用的Array…

信息安全与数学基础-笔记-③一次同余方程

知识目录一次同余方程的解中国剩余定理中国剩余定理的应用一次同余方程的解 本文只研究一次同余方程的解。 f(x) 三 0 (mod m), 若有一个s能够满足该式子,那么该数字就是该式子的解, 在同余方程式中的解一般写成:x三s (mod m) 同…

Git学习入门(2)- 基本命令操作总结

个人博客:我的个人博客,各位大佬来玩1 创建 git仓库1.1 从现有工作目录中初始化新仓库需要到你需要用git管理的项目中输入以下命令:git init便会创建一个空的git项目,并且当前目录下会出现一个名为 .git 的目录, Git 需…

1.SpringSecurity快速入门

*SpringScurity的核心功能: 认证:验证当前访问系统的是不是本系统的用户,并且要确认具体是哪个用户 授权:经过认证后判断当前用户是否有权限进行某个操作 *第一步:创建springboot工程 *第二步:引入SpringSecurity依赖 *第三步:写controller,访问对应的url:localhos…

常用训练tricks,提升你模型的鲁棒性

目录一、对抗训练FGM(Fast Gradient Method): ICLR2017代码实现二、权值平均1.指数移动平均(Exponential Moving Average,EMA)为什么EMA会有效?代码实现2. 随机权值平均(Stochastic Weight Averaging,SWA&a…

Java Volatile的三大特性

本文通过学习:周阳老师-尚硅谷Java大厂面试题第二季 总结的volatile相关的笔记volatile是Java虚拟机提供的轻量级的同步机制,三大特性为:保证可见性、不保证原子性、禁止指令重排一、保证可见性import java.util.concurrent.TimeUnit;class M…

cadence专题【1】--多引脚IC如何创建orcad原理图库

cadense下载说明新建工程一、采用传统方式创建1、新建库文件2、放置pin array3、修改管脚信息二、采用电子表格方式创建1、新建库文件2、Ctrlc、Ctrlvcadense下载说明 cadence是目前最流行的EDA,下载装机全交给阿狸狗即可。 浏览器搜索cadence吴川斌或点击链接: ht…

【aiy篇】小目标检测综述

小目标检测(Small Object Detection)是指在图像中检测尺寸较小的目标物体,通常是指物体的尺寸小于图像大小的1/10或者更小,COCO为例,面积小于等于1024像素的对象维下目标。小目标检测是计算机视觉领域的一个重要研究方…

记录一下,学习express的小成就

终于搞出来了mongoose 和express 前后端链接的部分。 主要目的是为了使用markdown转换网页。 项目随便写的。没有参考价值,在此只是为了做个记录。作为学习的一个里程碑。对于nodejs,终于可以自己探索,也算是入门了吧。 各位观众不要看了。…

深度学习 | 入个Pytorch的小门

本文主要参考 1’ 2’ 3 更新:2023 / 3 / 1 深度学习 | 入个Pytorch的小门 - 1. 常见数据操作创建操作算术操作加法索引形状查询形状改变形状广播机制广播条件运算数据类型转换Tensor转NumPyNumPy转Tensor线性回归线性回归的基本要素1. 模型2. 数据集3. 损失函数4.…

pycharm的License Certificate使用方法

1 在邮箱获得License Certificate的激活码之后,打开pycharm,选择HELP 在HELP菜单里选择Register 2 输入username or email和密码进行登录 3 登录之后,根据提示(如果有的话),进入官网如下页面&#xff0c…

LC-1599. 经营摩天轮的最大利润(贪心)

1599. 经营摩天轮的最大利润 难度中等39 你正在经营一座摩天轮,该摩天轮共有 4 个座舱 ,每个座舱 最多可以容纳 4 位游客 。你可以 逆时针 轮转座舱,但每次轮转都需要支付一定的运行成本 runningCost 。摩天轮每次轮转都恰好转动 1 / 4 周。…

Java奠基】方法的讲解与使用

目录 方法概述 方法的定义与调用 方法的重载 方法的值传递 方法概述 方法是程序中最小的执行单元,在实际开发中会将重复的具有独立功能的代码抽取到方法中,这样可以提高代码的复用性和可维护性。 方法的定义与调用 在Java中定义方法的格式都是相同…

leetcode 困难 —— 外星文字典(拓扑排序)

题目: 现有一种使用英语字母的外星文语言,这门语言的字母顺序与英语顺序不同。 给定一个字符串列表 words ,作为这门语言的词典,words 中的字符串已经 按这门新语言的字母顺序进行了排序 。 请你根据该词典还原出此语言中已知的字…

动态内存基础(二)

智能指针 ● 使用 new 与 delete 的问题:内存所有权不清晰,容易产生不销毁,多销毁的情况 int* fun() {int* res new int(100); //fun()拥有对fun()申请的内存的销毁权return res; } int main(int argc, char *argv[]) {QCoreApplication a(…

Java线程池-重点类源码解析--更新中

1.Runnable和Callable的区别 (1) Callable规定(重写)的方法是call(),Runnable规定(重写)的方法是run() (2) Callable的任务执行后可返回值,而Runnable的任务是不能返回值的 (3) call方法可以抛出异常&#…

总时差与自由时差

定义总时差(总浮动时间)(TF,Total Free Time,不耽误项目总进度)LS(Latest Start)-ES(Earliest Start)LF(Latest Finish)-EF&#xff0…

SpringCloud:Nacos配置管理

目录 一、统一配置管理 1、打开nacos控制台,点击配置管理,添加配置 2、编写配置 3、完成示例 ​二、服务配置拉取 1、引入Nacos配置管理客户端依赖 2、在resource目录添加一个bootstrap.yml文件,这个文件是引导文件,优先级高…

English Learning - L2 第 3 次小组纠音 [ʌ] [ɒ] [ʊ] [ɪ] [ə] [e] 2023.3.4 周六

English Learning - L2 第 3 次小组纠音 [ʌ] [ɒ] [ʊ] [ɪ] [ə] [e] 2023.3.4 周六共性问题小元音 [ʌ]小元音 [ɒ]小元音 [ʊ]小元音 [ɪ]小元音 [ə]小元音 [e]我的发音问题纠音过程共性问题 小元音 [ʌ] 口型容易偏大 解决办法:因为嘴角没有放松&#xff0c…

基于java的俱乐部会员管理系统

技术:Java、JSP等摘要:随着科学技术的飞速发展,科学技术在人们日常生活中的应用日益广泛,也给各行业带来发展的机遇,促使各个行业给人们提供更加优质的服务,有效提升各行业的管理水平。俱乐部通过使用一定的…