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

HashMap添加元素的流程图

文章目录

    • JDK7 vs JDK8 的 HashMap 结构变化
    • Java8 中哈希表的红黑树优化机制
    • HashMap 添加元素的完整流程解析
      • 1. 计算 key 的哈希值并确定索引
      • 2. 检查该索引位置是否已有元素
      • 3. 处理哈希冲突
      • 4. 判断当前存储结构(链表还是红黑树)
      • 5. 判断链表长度是否超过 8
      • 6. 触发扩容的判断
      • 7. 进行扩容
      • 8. 迁移元素
    • 流程图
    • 补充
      • HashMap 的初始容量与负载因子优化

JDK7 vs JDK8 的 HashMap 结构变化

在 JDK7 及更早版本,HashMap 采用 数组 + 链表 结构,当哈希冲突较多时,链表可能变得很长,导致查询性能从 O(1) 退化到 O(n)。

在 JDK8,为了优化链表查询性能,引入了红黑树

  • 仍然采用 数组 作为底层存储。
  • 当某个桶中的链表长度 超过 8,并且 table 的大小 ≥ 64 时,链表转换为 红黑树
  • 这样,在极端情况下,查询性能从 O(n) 降低到O(log n)

Java8 中哈希表的红黑树优化机制

从JDK8开始,为了优化哈希冲突情况下的查找性能,当哈希桶中的链表长度超过 8 时,链表会转换为红黑树。红黑树是一种自平衡二叉搜索树,将最坏情况下的查找复杂度从 O(n) 降低到 O(log n)。(如果没引入红黑树,则最坏查找复杂度是O(n))

当树中元素数量低于 6 时,红黑树会退化回链表,以减少不必要的树操作开销,提高小规模数据场景下的性能。

HashMap 添加元素的完整流程解析

1. 计算 key 的哈希值并确定索引

  • 通过 key.hashCode() 计算出哈希值。
  • 采用 (哈希值 & (table.length - 1)) 计算索引,以确定 key 应该存放在 table 数组中的那个位置。

2. 检查该索引位置是否已有元素

  • 如果该索引位置为空table[index] == null),说明当前 key 没有发生哈希冲突,直接存入该位置,并检查是否需要扩容。【在 HashMap 里,负载因子(loadFactor)默认值是 0.75,表示当元素个数达到 容量 * 0.75 时,就会触发扩容】
  • 如果该索引位置已有元素,说明发生了哈希冲突,进入下一步处理。

3. 处理哈希冲突

在索引位置已有元素的情况下,需要判断该 key 是否已经存在:

  • 如果 key 与已有节点的 key 相同,说明是更新操作,直接替换 value
  • 如果 key 不同,说明该索引位置是个链表或红黑树,需要进一步处理。

4. 判断当前存储结构(链表还是红黑树)

  • 如果该索引处存储的是红黑树,按照红黑树的插入规则执行插入操作,流程结束。
  • 如果是链表,则遍历链表:
    • 如果链表中存在相同的 key,则更新 value,流程结束。
    • 如果链表中没有相同 key,则在链表末尾插入新节点,并继续下一步处理。

5. 判断链表长度是否超过 8

  • 如果链表长度 ≤ 8,不做额外处理。
  • 如果链表长度 > 8,则需要判断是否转换为红黑树:
    • 如果 table 长度 >= 64,则将链表转换为红黑树,流程结束。
    • 如果 table 长度 < 64,则不转换为红黑树,而是触发扩容(见步骤 7)。

6. 触发扩容的判断

在完成插入后,需要判断是否需要扩容:

  • size >= 阈值(threshold = table.length * 0.75) 时触发扩容。
  • 扩容是基于整个 HashMap 的大小,而不是单个链表的长度,即使单个链表过长,也不会单独扩容,而是考虑整体 size

7. 进行扩容

  • 扩容策略table 容量翻倍(如 16 → 32,32 → 64)。
  • 调整扩容阈值:新阈值 = 新容量 * 0.75
  • 重新计算 key 的索引
    • 由于 table.length 发生变化,所有 key 需要重新计算索引并迁移到新的 table
    • HashMap 采用高位 & 低位拆分的方式优化了 rehash 过程,使得某些 key 的新索引保持不变,而另一些 key 需要移动到新位置。

8. 迁移元素

  • table 的数据逐个迁移到新 table
  • 迁移规则
    • 计算 oldIndex = hash & (oldCapacity - 1)newIndex = hash & (newCapacity - 1)
    • 低位不变,高位索引变化,减少数据迁移的计算量。

流程图

在这里插入图片描述


补充

HashMap 的初始容量与负载因子优化

HashMap 的默认初始容量为 16负载因子为 0.75,这一组合在性能与空间之间取得了平衡。较高的负载因子(如 1.0)可减少空间浪费,但会增加哈希冲突的概率;较低的负载因子则减少哈希冲突,但会增加内存开销。 (如果可预估 HashMap 的存储需求,建议提前设置合适的初始容量,以减少动态扩容带来的性能损耗。)

❤觉得有用的可以留个关注~~❤

相关文章:

  • Fiddler使用(一)
  • 嵌入式八股,什么是线程安全
  • 稀疏矩阵的存储
  • 美团 web 最新 mtgsig1.2
  • Spring MVC 拦截器使用
  • 大模型详细配置
  • 人工智能之数学基础:线性方程组求解的得力助手——增广矩阵
  • HarmonyOS Next~鸿蒙系统架构设计解析:分层、模块化与智慧分发的技术革新
  • DeDeCMS靶场攻略
  • pytest的测试报告allure
  • MongoDB 配合python使用的入门教程
  • 微软产品的专有名词和官方视频教程
  • 柔性PZT压电薄膜触觉传感器在人形机器人的应用
  • Android Launcher3终极改造:全屏应用展示实战!深度解析去除Hotseat的隐藏技巧
  • 如何设计大模型意图识别?
  • 学习笔记|arduino uno r3|DS1307时钟芯片|Atmega328P| 设置时间|读取时间|无源晶振:DS1307时钟芯片实验
  • 2025 使用docker部署centos7容器并且需要centos7容器能通过ssh登录SSH 登录的CentOS7容器
  • Linux CentOS7 安装 ffmpeg教程
  • 【总结】常用API架构类型
  • C++异常处理时的异常类型抛出选择
  • 在古老的意大利科莫歌剧院,廖昌永唱响16首中国艺术歌曲
  • 外交部:反对美方人士发表不负责任谬论
  • GDP逼近五千亿,向海图强,对接京津,沧州剑指沿海经济强市
  • 因操纵乙烯价格再遭诉讼,科莱恩等四家企业被陶氏索赔60亿
  • 75万买299元路由器后续:重庆市纪委、财政局、教委联合调查
  • 三亚通报救护车省外拉警报器开道旅游:违规违法,责令公司停业整顿