HashMap 原理(数据结构)

简介: HashMap 在 JDK 1.8 后采用数组+链表+红黑树实现。通过 key 的 hashCode 计算索引,存取效率为 O(1)。发生冲突时,使用链表或红黑树(链表长度 ≥ 8 且容量 ≥ 64 时树化),提升性能。数组默认容量 16,负载因子 0.75,超过阈值则扩容,容量翻倍。新增元素时,判断是否更新、链表插入或树化,并检查是否需要扩容。

jdk1.8以前底层数据结构:数组+链表

jdk1.8之后底层数据结构:数组+链表+红黑树

下面以jdk1.8之后来作介绍

  • 数组:存取元素时,利用 key 的 hashCode 来计算它在数组中的索引,这样在没有冲突的情况下,能让存取时间复杂度达到 O(1)
  • 冲突:数组大小毕竟有限,就算元素的 hashCode 唯一,数组大小是 n 的情况下要放入 n+1 个元素,根据鸽巢原理,肯定会发生冲突
  • 扩容因子:0.75 也就是 3/4
  • 初始容量 16,当放入第 13 个元素时(超过 3/4)时会进行扩容
  • 每次扩容,容量翻倍
  • 扩容后,会重新计算 key 对应的桶下标(即数组索引)这样,一部分 key 会移动到其它桶中
  • 解决冲突:一种办法就是利用链表,将这些冲突的元素链起来,当然在在此链表中存取元素,时间复杂度会提高为 O(n)
  • 树化目的是避免链表过长引起的整个 HashMap 性能下降,红黑树的时间复杂度是 O(log{n})

树化的时机

  • 时机:在数组容量达到 >= 64 且链表长度 >= 8 时,链表会转换成红黑树
  • 如果树中节点做了删除,节点少到已经没必要维护树,那么红黑树也会退化为链表


以下介绍HashMap 原理

以put加入一个对象进行说明

  1. 产生 hash 码。
  1. 先调用 对象里的hashCode() 方法
  2. 为了让哈希分布更均匀,还要对它返回结果进行二次哈希,这个结果称为 hash
  3. 二次哈希就是把 hashCode 的高 16 位与低 16 位做异或运算
  1. 存放的数组。
  1. 如果数组还不存在,会创建默认容量为 16 的数组,容量称为 n
  2. 否则使用已有数组
  1. 计算桶下标。
  1. 利用 (n - 1) & hash 得到 key 对应的桶下标(即数组索引)
  2. 也可以用 hash % n 来计算,但效率比前面的方法低,且有负数问题
  3. 用 (n - 1) & hash 有前提,就是容量 n 必须是 2 的幂(如 16,32,64 ...)
  1. 计算好桶下标后,分三种情况
  1. 如果该桶位置还空着,直接根据键值创建新的 Node 对象放入该位置即可
  2. 如果该桶是一条链表,沿着链表找,看看是否有值相同的 key,有走更新,没有走新增
  • 走新增逻辑的话,是把节点链到尾部(尾插法)
  • 新增后还要检查链表是否需要树化,如果是,转成红黑树
  • 新增的最后要检查元素个数 size,如果超过阈值,要走扩容逻辑
  1. 如果该桶是一棵红黑树,走红黑树新增和更新逻辑,同样新增的最后要看是否需要扩容
相关文章
|
2月前
|
人工智能 监控 算法
构建时序感知的智能RAG系统:让AI自动处理动态数据并实时更新知识库
本文系统构建了一个基于时序管理的智能体架构,旨在应对动态知识库(如财务报告、技术文档)在问答任务中的演进与不确定性。通过六层设计(语义分块、原子事实提取、实体解析、时序失效处理、知识图构建、优化知识库),实现了从原始文档到结构化、时间感知知识库的转化。该架构支持RAG和多智能体系统,提升了推理逻辑性与准确性,并通过LangGraph实现自动化工作流,强化了对持续更新信息的处理能力。
329 5
|
2月前
|
人工智能 自然语言处理 搜索推荐
提示词工程师到底是干什么的?
从小张想让AI助手帮他写代码却总是得到奇怪答案说起,揭开提示词工程师这个神秘职业的面纱。这个被称为'AI翻译官'的工作到底有多香?是时候考虑转行了吗?
|
2月前
|
存储 安全 前端开发
如何开发一套EHS 健康安全环境管理系统?(附架构图+流程图+代码参考)
本文介绍如何开发一套完整的EHS(健康、安全和环境)管理系统,涵盖系统核心模块、技术架构、数据库设计、前后端开发示例及上线建议,帮助企业提升安全管理效率与合规性。
|
2月前
|
JavaScript 前端开发 Java
=和==和=== 和 equals 的区别
本内容介绍了编程中常见的运算符与方法区别,包括赋值运算符“=”,比较运算符“==”,以及JavaScript中用于全等比较的“===”。同时说明了在Java中“==”和equals方法的区别
274 5
|
2月前
|
SQL 人工智能 JSON
Flink 2.1 SQL:解锁实时数据与AI集成,实现可扩展流处理
简介:本文整理自阿里云高级技术专家李麟在Flink Forward Asia 2025新加坡站的分享,介绍了Flink 2.1 SQL在实时数据处理与AI融合方面的关键进展,包括AI函数集成、Join优化及未来发展方向,助力构建高效实时AI管道。
631 43
|
2月前
|
人工智能 前端开发 调度
基于大模型的领域场景开发:从单智能体到多智能体的React框架设计与实现
本文介绍了基于大模型的领域场景开发演进过程,从提示词工程、RAG到流程编排,再到React模式的智能体架构升级。团队通过层级指挥模式实现单智能体自主规划与工具调用,并探索多智能体协作框架,提升复杂任务处理效率与灵活性。
598 19
基于大模型的领域场景开发:从单智能体到多智能体的React框架设计与实现
|
2月前
|
机器学习/深度学习 人工智能 算法
AI 基础知识从 0.4 到 0.5—— 计算机视觉之光 CNN
本文系统回顾了计算机视觉的发展历程,从早期基于手工特征的传统方法,到深度学习的崛起与卷积神经网络(CNN)的广泛应用,并通过数学原理、代码示例与可视化手段,全面解析了卷积操作的本质与CNN的架构设计。
320 33
AI 基础知识从 0.4 到 0.5—— 计算机视觉之光 CNN
|
2月前
|
SQL 关系型数据库 分布式数据库
一条SQL管理向量全生命周期,让AI应用开发更简单
本文探讨了AI应用开发中向量数据管理的挑战,介绍了PolarDB IMCI通过在数据库内核中集成向量索引与Embedding能力,实现向量全生命周期管理的创新方案。该方案有效解决了技术栈分裂、数据孤岛和运维复杂等痛点,提供了一体化、高性能、支持事务与实时检索的向量数据库服务,极大降低了AI应用的开发与维护门槛。
200 26
一条SQL管理向量全生命周期,让AI应用开发更简单
|
2月前
|
存储 NoSQL Java
我了解的java中常见的数据结构
本内容介绍了常见的数据结构,包括线性结构(如动态数组、链表、栈、队列)和非线性结构(如优先级队列、哈希表、红黑树、跳表、B+树),并结合 Java 中的具体实现(如 ArrayList、LinkedList、PriorityQueue、HashMap、TreeMap 等)说明其特点与应用场景。