当前位置: 首页 > article >正文

HashMap讲解

在Java开发中,HashMap 是最常用的数据结构之一,它不仅提供了键值对的快速存储和检索功能,还具备较高的性能和较低的空间占用。但很多开发者对其底层原理并不清楚,今天我们将详细解析HashMap的内部结构,并用通俗的方式解释其工作原理。

一、HashMap的基本概念
HashMap 是基于哈希表(Hash Table)实现的,它内部通过散列表存储数据。每一个键值对通过哈希函数被映射到散列表中的某个位置。这个数据结构最大的特点是能够实现以常数时间复杂度完成数据的插入和查找操作。

为了更深入理解HashMap,我们需要先了解它的核心组件。

二、核心组件解析
1. 数组(Node数组)
HashMap内部最基础的数据结构是一个Node<K,V>[]数组,其中每个元素是一个链表的头节点。这个数组用于存储键值对的链表,或者当链表长度超过一定值时,转为红黑树结构。

2. 哈希函数
每当向HashMap中添加一个键值对时,键(Key)首先会通过hashCode()方法生成一个哈希值。然后通过散列算法将哈希值映射到数组中的某个位置。这确保了键值对存储位置的合理分布,避免数据过度集中在某个位置。

通俗解释:你可以把HashMap看作是一个存放钥匙和箱子的货架。每把钥匙都有一个编号(哈希值),编号通过某种计算方式被映射到货架的某个位置(数组索引)。因此,你只需要通过这把钥匙就能快速找到存放的数据(箱子)。

3. 链表与红黑树
当多个键经过哈希函数后被映射到数组的同一个位置时,就会发生哈希冲突。为了处理这种冲突,HashMap使用链表来存储同一索引下的多个元素。

但是,当链表长度过长(Java 8 中的默认阈值为8),为了提高性能,HashMap会将链表转换为红黑树。红黑树是一种自平衡二叉查找树,能够以对数时间复杂度(O(log n))进行查找和插入操作。

通俗解释:如果很多钥匙被分配到了货架的同一个位置,HashMap会把这些钥匙挂成一条链子。当链子太长时,它就会变得难以寻找,HashMap会将这条链子改造成一棵“有序的树”,这样能够更快地找到数据。

4. 负载因子(Load Factor)
HashMap中有一个重要参数叫做负载因子,它决定了数组的扩容策略。负载因子是一个介于0和1之间的小数,它表示当HashMap的填充率超过这个值时,数组就会进行扩容。Java中默认的负载因子为0.75,即当HashMap填充率超过75%时,数组大小会翻倍。

通俗解释:你可以将HashMap想象成一个越来越满的货架,当货架上的数据超过75%时,货架会自动变大,提供更多的存储空间。

三、HashMap的工作过程
1. 添加数据
当你向HashMap中添加数据时,首先会通过键的hashCode()计算哈希值,然后根据哈希值找到数组中的存储位置。如果该位置没有发生冲突,键值对直接存入。如果发生冲突(即已有元素占用了这个位置),HashMap会通过链表或者红黑树的方式解决冲突。

2. 查询数据
查询操作时,HashMap首先通过键的哈希值定位到数组的某个位置。然后遍历该位置上的链表或红黑树,找到与查询键匹配的值。

3. 扩容
随着元素的不断增加,当填充率超过负载因子时,HashMap会执行扩容操作。扩容会创建一个更大的数组,并将原有元素重新分配到新的数组中。这个过程称为rehashing,因为所有元素都要重新计算哈希值并分配到新的位置。

四、常见问题与优化
1. 为什么链表长度超过8时会转成红黑树?
链表的查找时间复杂度是O(n),而红黑树的查找时间复杂度是O(log n)。当链表过长时,遍历查找会变慢,因此转成红黑树可以显著提高性能。

2. hashCode()与equals()方法的关系
为了确保HashMap的正确性,hashCode()和equals()方法必须正确实现。当两个键的hashCode()相同时,它们可能被映射到同一个位置。此时,HashMap还需要通过equals()方法判断键是否真正相同,以决定是覆盖旧值还是添加新值。

3. 并发问题
HashMap在并发环境下是不安全的。多个线程同时操作HashMap可能导致数据不一致问题。为了解决这个问题,可以使用线程安全的ConcurrentHashMap。

五、总结
HashMap通过哈希表、链表、红黑树等多种数据结构的结合,实现了高效的键值对存储与查询。其核心思想是通过哈希函数将数据均匀分布到数组中,避免了线性查找的低效问题。在实际使用中,理解HashMap的底层结构有助于写出更高效的代码,并在出现问题时快速找到原因。

通过本篇文章的深入解析,相信你已经对HashMap的底层原理有了更清晰的认识。希望大家在开发中能灵活运用,并注意其在高并发环境下的安全性问题。

相关文章:

HashMap讲解

在Java开发中&#xff0c;HashMap 是最常用的数据结构之一&#xff0c;它不仅提供了键值对的快速存储和检索功能&#xff0c;还具备较高的性能和较低的空间占用。但很多开发者对其底层原理并不清楚&#xff0c;今天我们将详细解析HashMap的内部结构&#xff0c;并用通俗的方式解…...

AIP-133 标准方法:Create

编号133原文链接AIP-133: Standard methods: Create状态批准创建日期2019-01-23更新日期2019-01-23 在REST API中&#xff0c;通常向集合URI&#xff08;如 /v1/publishers/{publisher}/books &#xff09;发出POST请求&#xff0c;在集合中创建新资源。 面向资源设计&#x…...

aerodrome交易所读合约分析

池地址 0xb2cc224c1c9fee385f8ad6a55b4d94e92359dc59token0 0x4200000000000000000000000000000000000006token1 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913tickSpacing 100stakedLiquidity 4579376109215388530 snapshotCumulativesInside tickLower tickUpperslot0 …...

ts 基础核心

吴悠讲编程 : 20分钟学会TypeScript 无废话速成TS https://www.bilibili.com/video/BV1gX4y177Kf...

[内网安全] 内网渗透 - 学习手册

这是一篇专栏的目录文档&#xff0c;方便读者系统性的学习&#xff0c;笔者后续会持续更新文档内容。 如果没有特殊情况的话&#xff0c;大概是一天两篇的速度。&#xff08;实验多或者节假日&#xff0c;可能会放缓&#xff09; 笔者也是一边学习一边记录笔记&#xff0c;如果…...

FaceFusion

文章目录 一、关于 FaceFusion预览 二、安装三、用法 一、关于 FaceFusion FaceFusion 是行业领先的人脸操作平台 github : https://github.com/facefusion/facefusion官方文档&#xff1a;https://docs.facefusion.io/Discord : https://discord.com/invite/facefusion-1141…...

使用github提交Pull Request的完整流程

文章目录 1.Fork仓库2. git clone 仓库在本地3.对项目进行修改开发4.上传项目到远程仓库操作补充1. git add .2. git commit -m "提交信息"3. git pull4. git push总结完整工作流程示例 5.将更新的项目pull Request给原来的仓库主人 当多人进行项目的开发的时候&…...

游戏与硬件深度协同,打造更精细的体验优化

高画质的游戏往往带来手机的发热和卡顿从而影响游戏体验。开发者希望能够获取到手机运行的实时状态&#xff0c;从而能够进行主动的负载调节&#xff0c;将手机发热时游戏体验影响降到最低&#xff1b;同时手机也可以通过游戏传入的关键场景如"正在下载资源"“团战中…...

简笔画生成smplx sketch2pose

目录 smplx安装: patch diff 命令行运行 pyrender报错: 解决方法: 这篇博客也不错,值得推荐 sketch2pose github地址: GitHub - kbrodt/sketch2pose: Sketch2Pose: Estimating a 3D Character Pose from a Bitmap Sketch smplx安装: 只能用这个版本,别的版本报错…...

SpringCloud系列教程:微服务的未来(十七)监听Nacos配置变更、更新路由、实现动态路由

前言 在微服务架构中&#xff0c;API 网关是各个服务之间的入口点&#xff0c;承担着路由、负载均衡、安全认证等重要功能。为了实现动态的路由配置管理&#xff0c;通常需要通过中心化的配置管理系统来实现灵活的路由更新&#xff0c;而无需重启网关服务。Nacos 作为一个开源…...

复古壁纸中棕色系和米色系哪个更受欢迎?

根据最新的搜索结果&#xff0c;我们可以看到棕色系和米色系在复古壁纸设计中都非常受欢迎。以下是对这两种颜色系受欢迎程度的分析&#xff1a; 棕色系 受欢迎程度&#xff1a;棕色系在复古壁纸中非常受欢迎&#xff0c;因为它能够营造出温暖、质朴和自然的氛围。棕色系的壁纸…...

Linux 非阻塞IO

Linux 非阻塞IO 1. fcntl() 在Linux操作系统中&#xff0c;fcntl() 是一个用于操作文件描述符的系统调用。它提供了多种功能&#xff0c;包括控制文件描述符的属性、管理文件锁定、设置文件的非阻塞模式等。 本文只截取了用于IO模型的 fcntl() 部分内容&#xff0c; fcntl() …...

go入门Windows环境搭建

简介 Go 即 Golang&#xff0c;是 Google 公司 2009 年 11 月正式对外公开的一门编程语言。 根据 Go 语言开发者自述&#xff0c;近 10 多年&#xff0c;从单机时代的 C 语言到现在互联网时代的 Java&#xff0c;都没有令人满意的开发语言&#xff0c;而 C往往给人的感觉是&a…...

es6中关于let的使用以及案例,包括但不限于块级作用域,不允许重复声明,没有变量提升,暂存性死区,不与顶层对象挂钩

ES6 let 关键字完整指南 1. 块级作用域 1.1 let vs var 作用域对比 // var - 函数作用域 function varExample() {var x 1;if (true) {var x 2; // 同一个 xconsole.log(x); // 2}console.log(x); // 2 }// let - 块级作用域 function letExample() {let x 1;if (true…...

IO进程线程复习

文件IO和标准IO的区别 文件IO: 1.系统提供的用于输入输出的函数 2.有文件描述符0&#xff0c;1&#xff0c;2 3.open,close,puts,gets 4.可以操作任意类型的文件&#xff0c;不能操作目录 5.无缓存机制 标准IO&#xff1a; 1.C库提供的用于输入输出的函数 2.有文件流&#xf…...

Mybatis初步了解

mysql缓存&#xff1a;根据sql语句进入缓存&#xff0c;如果sql语句多加一个空格就进入不到同一个缓存&#xff0c;另外数据库数据发生了更新&#xff0c;缓存中的数据不会同步。 延迟加载&#xff1a;先查询基本信息&#xff0c;再查询其他信息&#xff0c;而不是一次就查询出…...

基于PyQt设计的智能停车管理系统

文章目录 一、前言1.1 项目介绍【1】项目开发背景【2】设计实现的功能【3】设计意义【4】国内外研究现状【6】摘要1.2 设计思路1.3 系统功能总结1.4 开发工具的选择【1】VSCODE【2】python【3】ptqt【4】HyperLPR31.5 参考文献二、安装Python环境1.1 环境介绍**1.2 Python版本介…...

linux系统中的 scp的使用方法

SCP&#xff08;Secure Copy Protocol&#xff09;是一种通过加密的方式在本地主机和远程主机之间安全地传输文件的协议。 它是基于SSH协议的扩展&#xff0c;允许用户在不同主机之间进行文件复制和传输&#xff0c;是Linux和Unix系统中常用的工具之一。 在嵌入式Linux软件的…...

短连接项目01---基本框架的搭建和测试运行

文章目录 1.什么是短链2.仓库的创建3.项目的创建4.配置文件的修改5.三个模块的创建5.1如何创建5.2类型的选择5.3包的完善 6.yml文件的配置7.启动类的测试8可能会出现的问题 1.什么是短链 下面的这个就是一个长的url&#xff0c;我们的短链里面的链就是链接&#xff0c;也就是我…...

Unity阿里云OpenAPI 获取 Token的C#【记录】

获取Token using UnityEngine; using System; using System.Text; using System.Linq; using Newtonsoft.Json.Linq; using System.Security.Cryptography; using UnityEngine.Networking; using System.Collections.Generic; using System.Globalization; using Cysharp.Thr…...

2023年吉林省职业院校技能大赛网络系统管理样题-网络配置(华三代码)

目录 附录1:拓扑图 附录2:地址规划表 1.S1 2.S3 3.S4 4.S5 5.S7 6.S8 7.S9 8.R1 9.R2 10.R3 11.EG1 12.EG2 13.AC1 14.AC2 附录1:拓扑图 编号 型号...

WSL 安装cuDNN

WSL 安装cuDNN 参考文档&#xff1a;https://docs.nvidia.com/deeplearning/cudnn/installation/latest/linux.html#verifying-the-install-on-linux 1. 下载相应包 根据下方下载地址进入下载界面&#xff0c;并选择与自己电脑相对应的平台执行图中的命令 下载地址&#xff1…...

SSRF漏洞学习总结

一、SSRF漏洞 1.原理 SSRF&#xff08;Server-Side Request Forgery&#xff0c;服务器端请求伪造&#xff09;是一种安全漏洞&#xff0c;攻击者利用这个漏洞可以诱使服务器端发起由攻击者构造的请求。这种攻击通常发生在应用接受来自用户的输入&#xff0c;并且该输入用于构…...

stack 和 queue容器的介绍和使用

1.stack的介绍 1.1stack容器的介绍 stack容器的基本特征和功能我们在数据结构篇就已经详细介绍了&#xff0c;还不了解的uu&#xff0c; 可以移步去看这篇博客哟&#xff1a; 数据结构-栈数据结构-队列 简单回顾一下&#xff0c;重要的概念其实就是后进先出&#xff0c;栈在…...

Windows中本地组策略编辑器gpedit.msc打不开/微软远程桌面无法复制粘贴

目录 背景 解决gpedit.msc打不开 解决复制粘贴 剪贴板的问题 启用远程桌面剪贴板与驱动器 重启RDP剪贴板监视程序 以上都不行&#xff1f;可能是操作被Win11系统阻止 最后 背景 远程桌面无法复制粘贴&#xff0c;需要查看下主机策略组设置&#xff0c;结果按WinR输入…...

(2023 RESS ) Federated multi-source domain adversarial adaptation framework

&#x1f4da; 研究背景与挑战 机械设备的故障诊断对于保障生产效率和安全至关重要。传统的智能诊断方法依赖于大量的训练数据&#xff0c;但在实际工业场景中&#xff0c;数据收集受到经济和时间因素的限制。更棘手的是&#xff0c;由于行业竞争和隐私安全问题&#xff0c;不…...

Java实现FIFO缓存策略实战

实现FIFO模型选择FIFO模型实现过程FIFO模型完整代码下面看一下先进先出的示例过程总结FIFO(First In First Out,先进先出)策略是一种基本的数据处理和存储管理方法,在Java中,这种策略通常用于管理那些需要按照顺序处理的数据项,比如任务的队列、数据的传输缓冲区等。在Ja…...

虚幻基础07:蓝图接口

能帮到你的话&#xff0c;就给个赞吧 &#x1f618; 文章目录 作用原理事件函数 作用 实现对象间的通知。 A 通知 B 做什么。 原理 将接口抽象为蓝图&#xff0c;使得任意蓝图都能直接访问。 只需要再传入对象地址&#xff0c;就能执行对象的功能。 事件 黄色&#xff1a;…...

978.最长湍流子数组

目录 题目过程解法收获 题目 给定一个整数数组 arr &#xff0c;返回 arr 的 最大湍流子数组的长度 。 如果比较符号在子数组中的每个相邻元素对之间翻转&#xff0c;则该子数组是 湍流子数组 。 更正式地来说&#xff0c;当 arr 的子数组 A[i], A[i1], …, A[j] 满足仅满足…...

Python数据分析-Python语法基础,IPython和Jupyter-Notebooks(二)

title: ‘Python数据分析:Python语法基础&#xff0c;IPython和Jupyter Notebooks&#xff08;二&#xff09;’ tags: python数据分析 categories:python数据分析 keywords:python数据分析 cover: …/img/404_icecream_whale.png description: 本文介绍python的基础语法和jup…...