详解 HashMap 的底层实现原理

news2024/10/1 1:23:20

作为一名程序员,你可能经常使用 HashMap 这个重要的数据结构,但你对它的底层实现原理可能不够了解。本文将通过图文结合的方式,为你详细解析 HashMap 的底层实现原理,并回答一些常见问题,让你能够更好地理解和应用 HashMap。

1. HashMap 概述

HashMap 是 Java 集合框架中最常用的映射表实现,它提供了键值对的存储和检索功能。底层基于数组和链表(或红黑树)实现,通过哈希算法将键映射到数组的索引位置,以实现快速的插入和查找操作。下面我们来看一下 HashMap 的底层代码流程图:

2. HashMap 的主要方法分析

2.1 put方法

put方法用于将键值对插入到 HashMap 中。让我们看一下put方法的源代码:

首先,通过has(key)方法计算键的哈希码,并调用putVal()方法进行插入操作。下面是putVal()方法的源代码:

putVal()方法的核心是通过哈希码定位桶,然后在桶中进行插入操作。如果桶为空,则直接在桶中插入新节点。如果桶不为空,则遍历链表或红黑树,查找键是否已存在。如果键已存在,则替换对应的值;如果键不存在,则将新节点插入到链表的末尾,并根据链表长度是否达到阈值来决定是否将链表转化为红黑树。最后,更新修改次数和元素数量,并进行必要的操作。

2.2 resize方法

resize方法用于动态扩容 HashMap。当元素数量超过阈值时,HashMap 会自动触发扩容操作。下面是resize方法的源代码:

resize方法的主要功能是创建一个新的数组,并将所有键值对重新计算哈希码和索引位置,然后将它们分配到新的桶中。扩容后的容量是原来的两倍,并根据负载因子重新计算阈值。在转移键值对时,会根据哈希码的高位来确定是保留在原来的位置还是移动到新的位置。如果链表长度超过阈值,则会将链表转化为红黑树以提高查找效率。

2.3 get方法

当我们需要根据键来获取值时,可以使用 HashMap 的get(key)方法。下面讲解下 HashMap 的get方法的原理。

首先,我们传入要查找的键key,然后通过hash(key)方法计算键的哈希码。哈希码被用来确定键在 HashMap 中的桶(bucket)位置。根据哈希码,我们可以确定键在数组中的索引位置。

接下来,我们在确定的索引位置找到对应的桶。如果桶为空,即没有键值对存在,那么返回 null,表示没有找到对应的值。

如果桶不为空,那么可能存在多个键值对,这时我们需要遍历链表或红黑树来找到具有相同键的节点。在遍历过程中,我们会使用键的 equals() 方法来比较传入的键和当前节点的键是否相等。如果找到了相等的键,那么返回对应节点的值。

如果遍历完整个链表或红黑树仍然没有找到相等的键,那么返回 null,表示没有找到对应的值。

整个get()方法的原理就是根据键的哈希码确定索引位置,然后在对应的桶中遍历链表或红黑树,通过 equals() 方法比较键的相等性来找到对应的值。

以下是get方法的伪代码示例:

通过分析上述代码,我们可以看到get方法的实现流程:首先计算键的哈希码,然后根据哈希码找到对应的桶,最后在桶中遍历链表或红黑树,查找具有相同键的节点,如果找到则返回对应的值,否则返回 null。

3. 常见问题分析

3.1为什么哈希码很重要?

哈希码在 HashMap 中扮演着重要的角色。它通过哈希函数将键转换为一个唯一的整数,决定了键值对在数组中的存储位置。如果两个键的哈希码不同,它们会被分配到不同的桶中,提高了查找效率。如果哈希码相同,就会发生哈希冲突,需要进一步处理。

3.2如何处理哈希冲突?

当两个不同的键具有相同的哈希码时,HashMap 会使用链表或红黑树来解决哈希冲突。链表是 JDK 8 之前的解决方案,而红黑树是 JDK 8 之后的优化。HashMap 在桶中通过链表或红黑树结构存储冲突的键值对,以便在查找时能快速定位到正确的键值对。

3.3为什么需要动态扩容?

动态扩容是为了避免哈希冲突过多,提高 HashMap 的性能。当键值对的数量接近数组容量的阈值时,HashMap 会自动触发扩容操作。它创建一个更大的数组,并重新计算每个键的哈希码和索引位置,然后将键值对重新插入到新数组中。这样可以减少桶的数量,降低哈希冲突的概率,提高存储和检索的效率。

3.4如何保证键的唯一性?

HashMap 通过哈希码和链表/红黑树结构来保证键的唯一性。当存储键值对时,如果发现相同的键已经存在于桶中,HashMap 会检查键的 equals() 方法来确定是否是同一个键。如果 equals() 方法返回 true,新的键值对会替换旧的键值对;如果 equals() 方法返回 false,新的键值对会被添加到桶中。这样就确保了 HashMap 中的键是唯一的。

3.5HashMap 和线程安全有关吗?

HashMap 在默认情况下是非线程安全的。多个线程同时对 HashMap 进行插入、删除或查找操作可能会导致不一致的结果。如果在并发环境下使用 HashMap,应考虑使用线程安全的 ConcurrentHashMap 或使用适当的同步机制来保护 HashMap 的访问。

3.6如何选择适当的初始容量和负载因子?

HashMap 的初始容量和负载因子会影响其性能和空间利用率。初始容量是指 HashMap 初始化时的桶数量,默认为 16。负载因子是指 HashMap 在扩容之前允许的平均桶占用比例,默认为 0.75。

选择适当的初始容量和负载因子取决于你的应用需求。如果预计存储的键值对数量较多,可以选择一个较大的初始容量,以减少动态扩容的频率。负载因子较小可以减少哈希冲突的概率,但会增加空间占用。综合考虑,通常可以使用 HashMap 的默认值,并根据实际情况进行调整。

HashMap 是一个强大而灵活的数据结构,合理使用它可以提高程序的性能和效率。通过深入了解 HashMap 的底层实现原理,你可以更好地理解其工作方式,并在实际开发中做出更明智的设计和优化决策。

相关内容拓展:(技术前沿)

近10年间,甚至连传统企业都开始大面积数字化时,我们发现开发内部工具的过程中,大量的页面、场景、组件等在不断重复,这种重复造轮子的工作,浪费工程师的大量时间。

针对这类问题,低代码把某些重复出现的场景、流程,具象化成一个个组件、api、数据库接口,避免了重复造轮子。极大的提高了程序员的生产效率。

推荐一款程序员都应该知道的软件JNPF快速开发平台,采用业内领先的SpringBoot微服务架构、支持SpringCloud模式,完善了平台的扩增基础,满足了系统快速开发、灵活拓展、无缝集成和高性能应用等综合能力;采用前后端分离模式,前端和后端的开发人员可分工合作负责不同板块,省事又便捷。

免费体验官网:https://www.jnpfsoft.com/?csdn。还没有了解低代码这项技术可以赶紧体验学习!


结论

通过以上的源代码分析和常见问题的解答,相信你已经对 HashMap 的底层实现原理有了更深入的理解。HashMap 的底层使用数组和链表(或红黑树)实现,通过哈希算法将键映射到数组的索引位置,以实现快速的插入和查找操作。动态扩容过程会创建一个更大的数组,并重新分配键值对到新的桶中,以提高性能。同时,我们还回答了一些常见问题,希望能帮助你更好地理解和应用 HashMap。

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

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

相关文章

电商分析:微商城还有入局的必要吗?

电商行业发展日新月异,新模式、新平台不断涌现。微商城系统作为一种新型的电商模式,正逐渐受到越来越多的关注和青睐。那么,微商城系统还有入局的必要吗? 首先,我们需要了解一下什么是微商城系统。微商城系统是一种基于…

SphereEx-DBPlusEngine 1.5.0 功能解读:CDC

前一段时间,面向新一代数据架构的数据库增强引擎 SphereEx-DBPlusEngine 正式发布 1.5.0 版本,新增 CDC 和数据库防火墙两大重磅功能,本篇文章笔者就给大家详细介绍 CDC 功能的实现逻辑和技术细节。 CDC CDC(Change Data Captur…

LeetCode 27题:移除元素

题目 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。 不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。 元素的顺序可以改变。你不需要考虑数组中超出新长…

概念解析 | 利用IAA迭代自适应方法实现高精度角度估计

利用IAA迭代自适应方法实现高精度角度估计 注1:本文系“概念辨析”系列之一,致力于简洁清晰地解释、辨析复杂而专业的概念。本次辨析的概念是:IAA迭代自适应方法在雷达角度估计中的应用。 背景介绍 在雷达目标检测与定位中,准确估计目标角度是实现高精度定位的关键。传统的基于…

【FAQ】如何隐藏网页H.265播放器EasyPlayer.js的实时录像按钮?

目前我们TSINGSEE青犀视频所有的视频监控平台,集成的都是EasyPlayer.js版播放器,它属于一款高效、精炼、稳定且免费的流媒体播放器,可支持多种流媒体协议播放,包括WebSocket-FLV、HTTP-FLV,HLS(m3u8&#x…

2023最新版本Activiti7系列-监听器讲解

监听器 1.执行监听器 在流程实例执行过程中触发某个事件时,Activiti提供的执行监听器可以捕获该事件并执行相应的外部的Java代码,或者对指定的表达式求值。在流程实例执行过程中触发某个事件时,Activiti提供的执行监听器可以捕获该事件并执行…

《动手学深度学习》-67自注意力

沐神版《动手学深度学习》学习笔记,记录学习过程,详细的内容请大家购买书籍查阅。 b站视频链接 开源教程链接 自注意力 在深度学习中,经常使用卷积神经网络(CNN)或循环神经网络(RNN)对序列进行…

【暑期每日一练】 day14

目录 选择题 (1) 解析: (2) 解析: (3) 解析: (4) 解析: (5) 解析: 编程题 题一 …

全球十大知名看黄金即时行情的软件名单(综合榜单)

在当今的数字化时代,黄金投资已成为一种受欢迎的投资方式。为了获取即时的黄金行情信息,许多投资者开始使用黄金即时行情软件。然而,选择一款合适的软件并不是一件容易的事情。那么,如何选适合自己需求的软件呢?首先&a…

Hyper实现git bash在windows环境下多tab窗口显示

1.电脑上安装有git bash 下载链接:https://gitforwindows.org/ 安装Hyper 下载链接:官网 https://hyper.is/ 或者在百度云盘下载: https://pan.baidu.com/s/1BVjzlK0s4SgAbQgsiK1Eow 提取码:0r1f 设置 打开Hyper,依次点左上角-&g…

Arduino驱动MQ5模拟煤气气体传感器(气体传感器篇)

目录 1、传感器特性 2、硬件原理图 3、驱动程序 MQ5气体传感器,可以很灵敏的检测到空气中的液化气、天然气、煤气等气体,与Arduino结合使用,可以制作火灾液化气、天然气、煤气泄露报警等相关的作品。 1、传感器特性 MQ5用于消费和工业行业中气体泄漏检测设备,该传感器适…

【网络】DNS、ICMP、NAT

目录 一、DNS(Domain Name System) 1、DNS背景 2、域名简介 二、ICMP协议 1、ICMP功能 2、ICMP的报文格式 3、ping命令 4、traceroute命令 三、NAT技术 1、NAT技术背景 2、NAT IP转换过程 3、NAPT 4、NAT技术的缺陷 5、NAT和代理服务器 一、DNS(Domain Name Syste…

分布式应用:Zookeeper 集群与kafka 集群部署

目录 一、理论 1.Zookeeper 2.部署 Zookeeper 集群 3.消息队列 4.Kafka 5.部署 kafka 集群 6.FilebeatKafkaELK 二、实验 1.Zookeeper 集群部署​​​​​​​ 2.kafka集群部署 3.FilebeatKafkaELK 三、问题 1.解压文件异常 2.kafka集群建立失败 3.启动 filebeat报…

中国信通院发布《高质量数字化转型产品及服务全景图(2023)》

2023年7月27日,由中国信息通信研究院主办的2023数字生态发展大会暨中国信通院铸基计划年中会议在北京成功召开。 本次大会发布了中国信通院《高质量数字化转型产品及服务全景图(2023)》,中新赛克海睿思受邀出席本次大会并成功入选…

HarmonyOS应用开发者基础与高级认证题库——中级篇

系列文章目录 HarmonyOS应用开发者基础与高级认证题库——基础篇 HarmonyOS应用开发者基础与高级认证题库——中级篇 文章目录 系列文章目录前言一、判断二、单选三、多选 前言 今天刚换了台果子手机就收到了华子鸿蒙开发认证邀请(认证链接)&#xff0…

2020年江西省职业院校技能大赛高职组“信息安全管理与评估”赛项任务书

2020年江西省职业院校技能大赛高职组 “信息安全管理与评估”赛项任务书 赛项时间 9:00-12:00,共计3小时。 赛项信息 赛项内容 竞赛阶段 任务阶段 竞赛任务 竞赛时间 分值 第一阶段 平台搭建与安全设备配置防护 任务1 网络平台搭建 9:00-12:00 100 任务…

2023下半年软考初级程序员报名入口-报名流程-备考方法

软考初级程序员2023下半年考试时间: 2023年下半年软考初级程序员的考试时间为11月4日、5日。考试时间在全国各地一致,建议考生提前备考。共分两科,第一科基础知识考试具体时间为9:00到11:30;第二科应用技术考试具体时间为2:00到4…

【C++刷题集】-- day5

目录 选择题 单选 编程题 统计回文⭐ 【题目解析】 【解题思路 - 穷举】 【优化】 连续最大和⭐ 【题目解析】 【解题思路】 【空间优化】 选择题 单选 1、 在上下文和头文件均正常情况下,以下程序的输出结果是 ( ) int x 1; do {printf("%2d\n&q…

Python批量查字典和双语例句

最近,有网友反映,我的批量查字典工具换到其它的网站就不好用了。对此,我想说的是,互联网包罗万象,网站的各种设置也有所不同,并不是所有的在线字典都可以用Python爬取的。事实上,很多网站为了防…

Python入门自学进阶-Web框架——38、redis、rabbitmq、git

缓存数据库redis: NoSQL(Not only SQL)泛指非关系型的数据库。为了解决大规模数据集合多重数据类的挑战。 NoSQL数据库的四大分类: 键值(Key-Value)存储数据库列存储数据库文档型数据库图形(…