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

HashMap中get()、put()详解

一、介绍

HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。

HashMap 实现了 Map 接口,根据键的 HashCode 值存储数据,具有很快的访问速度,最多允许一条记录的键为 null,不支持线程同步。

HashMap 是无序的,即不会记录插入的顺序。

HashMap 如果再次添加相同的key值,它会覆盖key值所对应的内容。

HashMap 继承于AbstractMap,实现了 Map、Cloneable、java.io.Serializable 接口。

HashMap是:数组+链表+红黑树(JDK1.8增加了红黑树部分)的数据结构,其中数组的每个元素称为桶(bucket),数组的大小(容量)通常是 2 的幂次方。每个桶可以存储一个链表或红黑树,用于解决哈希冲突。当链表的长度超过一定阈值(默认为 8)时,链表会转换为红黑树,以提高查找效率。

二、常用方法

方法描述
clear()删除 hashMap 中的所有键/值对
clone()复制一份 hashMap
isEmpty()判断 hashMap 是否为空
size()计算 hashMap 中键/值对的数量
put()将键/值对添加到 hashMap 中
putAll()将所有键/值对添加到 hashMap 中
putIfAbsent()如果 hashMap 中不存在指定的键,则将指定的键/值对插入到 hashMap 中。
remove()删除 hashMap 中指定键 key 的映射关系
containsKey()检查 hashMap 中是否存在指定的 key 对应的映射关系。
containsValue()检查 hashMap 中是否存在指定的 value 对应的映射关系。
replace()替换 hashMap 中是指定的 key 对应的 value。
replaceAll()将 hashMap 中的所有映射关系替换成给定的函数所执行的结果。
get()获取指定 key 对应对 value
getOrDefault()获取指定 key 对应对 value,如果找不到 key ,则返回设置的默认值
forEach()对 hashMap 中的每个映射执行指定的操作。
entrySet()返回 hashMap 中所有映射项的集合集合视图。
keySet()返回 hashMap 中所有 key 组成的集合视图。
values()返回 hashMap 中存在的所有 value 值。
merge()添加键值对到 hashMap 中
compute()对 hashMap 中指定 key 的值进行重新计算
computeIfAbsent()对 hashMap 中指定 key 的值进行重新计算,如果不存在这个 key,则添加到 hashMap 中
computeIfPresent()对 hashMap 中指定 key 的值进行重新计算,前提是该 key 存在于 hashMap 中。

三、 重要方法详解

1、哈希函数(hash方法)

源码详解:

参数 key:需要计算哈希码的键值。

key == null ? 0 : (h = key.hashCode()) ^ (h >>> 16)这是一个三目运算符,如果键值为 null,则哈希码为 0(依旧是说如果键为 null,则存放在第一个位置);否则,通过调用hashCode()方法获取键的哈希码,并将其与右移 16 位的哈希码进行异或运算。

^ 运算符:异或运算符是 Java 中的一种位运算符,它用于将两个数的二进制位进行比较,如果相同则为 0,不同则为 1。

h >>> 16将哈希码向右移动 16 位,相当于将原来的哈希码分成了两个 16 位的部分。

最终返回的是经过异或运算后得到的哈希码值。

        HashMap 的底层是通过数组的形式实现的,初始大小是 16。使用哈希函数将键映射到数组的索引位置。哈希函数通常包括两部分:计算键的哈希码(hashCode)和将哈希码映射到数组索引。

 

2、get()方法

 

通过源码可以分析发现,get 方法调用 getNode 方法,传入键的哈希值和键。

getNode 方法首先检查数组是否为空,以及对应索引位置的桶是否为空。

如果桶的第一个节点匹配,则返回该节点。

如果桶是红黑树,则调用红黑树的查找方法。

如果桶是链表,则遍历链表查找匹配的节点

3、put()方法

执行过程整体如下:

① 判断键值对数组 table[i] 是否为空或为null,否则执行 resize() 进行扩容;

② 根据键值 key计算hash值得到插入的数组索引i,如果table[i]==null,直接新建节点添加;

③ 判断table[i]的首个元素是否和key一样,如果相同直接覆盖value;

④ 判断table[i] 是否为treeNode,即table[i] 是否是红黑树,如果是红黑树,则直接在树中插入键值对;

⑤ 遍历table[i],判断链表长度是否大于8,大于8的话把链表转换为红黑树,在红黑树中执行插入操作,否则进行链表的插入操作;遍历过程中若发现key已经存在直接覆盖value即可;

⑥ 插入成功后,判断实际存在的键值对数量size是否超多了最大容量threshold,如果超过,进行扩容。

 简单总结来说,分成四种情况:1、数组下标下内容为空直接放;2、数组下标下内容不为空,并且引用的node还没有链化。如果传的key与之前的相同则直接把旧value替换为新的,如果不一样就形成链表(尾插);3、已经有链表了,按链表的方式查,和前面一样如果key相同替换,不相同尾插;4、已经形成红黑树,按红黑树的方式查找。

http://www.dtcms.com/a/271297.html

相关文章:

  • 代码审计-shiro漏洞分析
  • Explain关键字
  • rt thread studio 和 KEIL对于使用rt thread 的中间件和组件,哪个更方便
  • Flask3.1打造极简CMS系统
  • VsCode 接入Continue 远程调用(持续扩展 + DeepSeek R1)— 免本地算力
  • ZECN致业:科创微光,照亮技术新征程
  • 200nl2sql
  • Linux建立本地软件仓库
  • 存储服务一NFS文件存储概述
  • 解锁HTML5页面生命周期API:前端开发的新视角
  • debug和release的区别,打印菱形,水仙花数,喝汽水问题,计算求和
  • 从互联网电脑迁移Dify到内网部署Dify方法记录
  • 语音识别核心模型的数学原理和公式
  • http get和http post的区别
  • 【软件工程】tob和toc含义理解
  • 【25软考网工】第十章 (3)网络冗余设计、广域网接入技术
  • Docker 高级管理 -- 容器通信技术与数据持久化
  • mysql 故障检测与处理
  • Linux 测开:日志分析 + 定位 Bug
  • Paimon 原子提交实现
  • 【Linux】Rocky Linux 安装 Docker 与 Docker-Compose
  • AI智能选股,DeepSeek智能分析股票测试
  • 搭建一款结合传统黄历功能的日历小程序
  • C++最小生成树算法详解
  • 人机协同的关键枢纽:软件工程3.0中对象模型与模型驱动的融合路径
  • Vue 3 中父子组件双向绑定的 4 种方式
  • 如何将 AWS EBS 卷从 gp2 批量迁移到 gp3:完整指南
  • 基于Spring Boot+Vue的DIY手工社预约管理系统(Echarts图形化、腾讯地图API)
  • [Pytest][Part 4]多种测试运行方式
  • docker部署华为高斯数据库opengauss(arm版本)