从链表到红黑树:全面剖析 JDK 1.7 与 JDK 1.8 中的 HashMap 实现

在 Java 开发中,HashMap 是一个非常常用的数据结构。它的高效性和便捷性使得它在各种应用场景中被广泛使用。然而,很多开发者对 HashMap 的底层实现并不是非常了解,尤其是在 JDK 1.7 和 JDK 1.8 之间的实现差异。本文将深入探讨 HashMap 的底层实现以及相关机制。

HashMap 在 JDK 1.7 和 JDK 1.8 中的实现差异

JDK 1.7:数组 + 链表

在 JDK 1.7 中,HashMap 是通过数组和链表来实现的。每个数组元素是一个链表的头节点,当发生哈希冲突时,新元素将被添加到链表的末尾。虽然这种方式实现简单,但在链表过长的情况下,查询效率会显著下降,时间复杂度为 O(n)。

JDK 1.8:数组 + 链表 / 红黑树

为了优化查询效率,JDK 1.8 引入了红黑树。当链表长度超过 8 且数组长度大于 64 时,链表会转化为红黑树,从而将时间复杂度降至 O(logn)。这种改进显著提高了在大数据量下的查询效率。

HashMap 的新增流程

HashMap 的新增元素流程可以分为以下几个步骤:

  1. 计算哈希值:将 key 进行 hash 计算,得到哈希值。
  2. 确定位置:根据哈希值确定元素在数组中的位置。
  3. 插入元素
    • 如果位置为空,直接插入。
    • 如果位置不为空,判断是否为红黑树。如果是红黑树,则直接插入。
    • 如果是链表,判断链表长度是否超过 8 且数组长度是否大于 64。如果满足条件,则链表转化为红黑树,然后插入元素。如果不满足条件,则遍历链表进行插入。
为什么链表要升级为红黑树?

在 JDK 1.8 及以上版本中,当链表长度达到 8 且数组长度大于等于 64 时,链表会转换为红黑树。这是因为链表在长度较长时查询效率很低,时间复杂度为 O(n),而红黑树的时间复杂度为 O(logn)。引入红黑树可以大幅提高查询效率。

红黑树退化为链表的情况

当 TreeNode 的长度小于 6 时,红黑树会退化为链表。这种机制是为了在小数据量情况下降低不必要的复杂性和资源消耗。

HashMap 中使用红黑树的原因

HashMap 选择红黑树主要有以下几个原因:

  1. 二分查找树的不平衡性:二分查找树可能在极端情况下退化为链表,查询效率低。
  2. 链表查询效率低:链表长度越长,插入和查询效率越低。
  3. 红黑树效率高:红黑树的查找、插入和删除操作的效率都很高,是一种自平衡的二叉树结构。

综合考虑,红黑树是 HashMap 的最佳选择。

HashMap 重要的参数

HashMap 有两个重要的参数:容量(Capacity)和加载因子(LoadFactor)。

  1. 容量(Capacity):指 HashMap 中桶的数量,默认初始值为 16。
  2. 加载因子(LoadFactor):判定 HashMap 是否扩容的依据,默认值为 0.75。加载因子为 size / Capacity。
为什么加载因子是 0.75?

这是容量和性能之间平衡的结果。加载因子较大时,扩容频率低,但哈希冲突几率增加,性能下降。加载因子较小时,占用空间多,但哈希冲突几率小,性能较高。0.75 是一个折中的选择。

HashMap 如何解决哈希冲突?

在 JDK 1.8 中,HashMap 通过链式寻址法和红黑树解决哈希冲突。当链表长度超过 8 且数组容量大于 64 时,链表转化为红黑树,从而优化查询效率。

ConcurrentHashMap 如何保证线程安全?

在 JDK 1.7 中,ConcurrentHashMap 通过分段锁保证线程安全。而在 JDK 1.8 中,则采用了头节点加锁,结合 CAS + volatile 或 synchronized 的方式来保证线程安全。

相关推荐
不会C语言的男孩38 分钟前
C++ Primer 第3章:字符串、向量和数组
开发语言·c++
兰令水40 分钟前
leecodecode【反前后指针】【2026.5.31打卡-java版本】
java·开发语言
Dovis(誓平步青云)2 小时前
《QT学习第四篇:常见事件与UDP、TCP、文件系统、(锁、信号量、条件变量》
c语言·开发语言·汇编·qt
AI人工智能+电脑小能手8 小时前
【大白话说Java面试题 第87题】【Mysql篇】第17题:分布式事务的实现原理?
java·数据库·分布式·mysql·面试
来杯@Java9 小时前
图书管理系统(基于springboot+vue前后端分离的项目)计算机毕业设计java
java·spring boot·spring·vue·毕业设计·mybatis·课程设计
卷毛的技术笔记10 小时前
告别硬编码!Spring AI Alibaba 实现 AI Agent 智能工具调用(Tool Calling)
java·人工智能·后端·python·spring·ai编程
编程大师哥10 小时前
匿名函数 lambda + 高阶函数
java·python·算法
isyangli_blog10 小时前
OpenDayLight (Carbon 版本) 启动与组件安装
开发语言·php
vb20081110 小时前
FastAPI APIRouter
开发语言·python
Benszen10 小时前
KVM虚拟化解决方案
开发语言·perl