集合(四):LinkedHashMap深度解析——有序哈希与 LRU 缓存的基石

LinkedHashMap与HashMap深度对比:从原理到LRU缓存实战 在Java集合框架中,哈希表是实现高效键值对存储的核心数据结构。其基本原理是通过哈希函数将键映射到数组索引,从而实现接近O(1)时间复杂度的查找操作。然而,标准哈希表(如HashMap)不维护元素的插入或访问顺序,这在需要保持元素顺序或实现特定淘汰策略(如LRU缓存)的场景中存在局限。为了解决这一问题,LinkedHashMap在继承HashMap哈希表结构的基础上,通过维护一个贯穿所有节点的双向链表,巧妙地记录了元素的顺序。这一设计使其在保持高效查找的同时,能够以O(1)成本维护两种顺序模式:插入顺序和访 阅读详情

在 Java 集合框架中,HashMap 以其高效的查找性能称霸,但它有一个痛点:无序。当你需要一个既能快速查找,又能保持插入顺序(或访问顺序)的容器时,LinkedHashMap 便是最佳选择。

本文将揭示 LinkedHashMap 如何通过“双重结构”实现有序性,并展示如何利用其独有的机制,用短短几行代码实现一个 LRU (Least Recently Used) 缓存。

1. 核心架构:哈希表与链表的完美融合

LinkedHashMap 继承自 HashMap,它并没有重写哈希算法,而是通过在原有哈希桶的基础上,维护了一条双向链表。

1.1 结构思维导图

LinkedHashMap

继承关系

extends HashMap

implements Map

核心数据结构

哈希表 (数组 + 链表/红黑树): 保证 O(1) 查找

双向链表 (head + tail): 保证迭代顺序

关键属性

accessOrder

false (默认): 插入顺序

true: 访问顺序 (LRU 核心)

Entry 节点

继承 HashMap.Node

新增 before 指针

新增 after 指针

实战应用

LRU 缓存

有序配置加载

1.2 节点结构的秘密

普通的 HashMap 节点只有 next 指针(用于处理哈希冲突)。而 LinkedHashMap 的节点(Entry)增加了 before and after 指针,用于串联起所有元素。

// LinkedHashMap 内部类 Entry
static class Entry<K,V> extends HashMap.Node<K,V> {
    Entry<K,V> before, after; // 双向链表的指针
    
    Entry(int hash, K key, V value, Node<K,V> next) {
        super(hash, key, value, next);
    }
}

1.3 结构示意图

下图展示了 LinkedHashMap 的内存视图。注意看,数据既存在于哈希桶中(垂直方向),也被一条双向链表(水平方向的红色虚线)串联起来。

HashMap Structure

after

before

after

before

after

before

Bucket 0

Bucket 1

Bucket 2

Bucket 3

Key: A
Val: 1

Key: B
Val: 2

Key: C
Val: 3

Key: D
Val: 4


2. 核心机制:accessOrder 与 顺序维护

LinkedHashMap 的构造函数中有一个至关重要的参数:accessOrder。

  • accessOrder = false (默认): 插入顺序。新插入的元素放在链表末尾;读取元素不会改变链表顺序。
  • accessOrder = true: 访问顺序。每当 get 或 put 一个已存在的元素时,该元素会被移动到链表的末尾。

2.1 访问顺序移动流程(LRU 基础)

假设我们开启了 accessOrder = true,当前链表为 A <-> B <-> C。当我们调用 get("A") 时:

DoubleLinkedList LinkedHashMap Client DoubleLinkedList LinkedHashMap Client 将 A 从当前位置断开 将 A 移动到链表尾部 get("A") 查找 Key "A" (HashMap逻辑) afterNodeAccess(Node A) 链表变为 B <->> C <->> A return Value A

2.2 源码解析:afterNodeAccess

HashMap 预留了三个回调方法给子类实现,LinkedHashMap 重写了其中的 afterNodeAccess。

// 当 accessOrder 为 true 时,将当前节点 e 移到双向链表尾部
void afterNodeAccess(Node<K,V> e) { 
    LinkedHashMap.Entry<K,V> last;
    // 条件:accessOrder 为 true 且 当前节点不是尾节点
    if (accessOrder && (last = tail) != e) {
        // ... (省略具体的指针断开与重连代码) ...
        // 核心逻辑:
        // 1. 将 e 从 before 和 after 之间移除
        // 2. 将 e 接到 tail 后面
        // 3. tail 指向 e
    }
}

3. 实战:3分钟实现 LRU 缓存

LRU (Least Recently Used) 是一种常见的缓存淘汰算法:当缓存满时,优先淘汰最近最少使用的数据。

利用 LinkedHashMap 的 accessOrder=true 特性,链表头部就是“最近最少使用”的元素,尾部是“最近刚被使用”的元素。我们只需要在插入新元素导致容量溢出时,移除链表头部的元素即可。

3.1 关键方法:removeEldestEntry

LinkedHashMap 提供了一个受保护的方法 removeEldestEntry。在每次 put 新元素后,HashMap 会调用这个方法。

  • 默认实现返回 false(永不移除)。
  • 我们需要重写它:当 size() > capacity 时返回 true。

3.2 LRU 缓存完整代码

import java.util.LinkedHashMap;
import java.util.Map;

public class LRUCache<K, V> extends LinkedHashMap<K, V> {
    
    private final int capacity;

    public LRUCache(int capacity) {
        // 1. 设置初始容量
        // 2. loadFactor 设为 0.75
        // 3. 关键点:accessOrder 设为 true (按访问顺序排序)
        super(capacity, 0.75f, true);
        this.capacity = capacity;
    }

    /**
     * 核心钩子方法
     * 每次 put 操作后,LinkedHashMap 会调用此方法
     * 如果返回 true,则移除链表最老的节点(头部节点)
     */
    @Override
    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
        return size() > capacity;
    }

    // 测试代码
    public static void main(String[] args) {
        // 创建一个容量为 3 的 LRU 缓存
        LRUCache<String, Integer> cache = new LRUCache<>(3);

        cache.put("A", 1);
        cache.put("B", 2);
        cache.put("C", 3);
        System.out.println("初始状态: " + cache); // [A, B, C]

        cache.get("A"); // 访问 A,A 变成最新的,移到尾部
        System.out.println("访问 A 后: " + cache); // [B, C, A]

        cache.put("D", 4); // 插入 D,容量超标,淘汰最老的 B
        System.out.println("插入 D 后: " + cache); // [C, A, D]
    }
}

3.3 LRU 淘汰流程图

是

否

put 新元素 D

HashMap 插入 D

将 D 链接到链表尾部

调用 removeEldestEntry
size > capacity ?

移除链表头部节点
(最近最少使用的)

结束


LinkedHashMap 是 Java 集合框架中设计非常精妙的一个类,它展示了如何通过组合现有的数据结构(数组+链表)来满足复杂的业务需求。

  1. 双重结构:继承 HashMap 保证查询效率,内部维护双向链表保证迭代顺序。
  2. accessOrder:决定了是按“插入顺序”还是“访问顺序”维护链表,这是实现 LRU 的开关。
  3. 扩展性:通过预留的 removeEldestEntry 钩子方法,极大地简化了缓存淘汰策略的实现。
LinkedHashMap与TreeMap深度对比:有序Map选型指南与实战应用 在Java集合框架中,Map是存储键值对的核心数据结构,其无序特性常需有序方案来补充。有序Map通过维护元素顺序,解决了数据遍历、缓存管理和范围查询等常见需求。其实现原理主要分为两类:基于哈希表与双向链表组合的插入/访问顺序维护,以及基于红黑树的自平衡排序机制。从技术价值看,有序Map提升了数据访问的可预测性和特定场景下的操作效率,例如实现LRU缓存或支持高效的范围检索。在应用场景上,需要保持元素插入或访问顺序的日志处理、会话管理适合使用LinkedHashMap;而需要按键的自然顺序或自定义顺序进行排序、 阅读详情

相关推荐

深度剖析Java集合之LinkedHashMap

LinkedHashMap 的put 流程,特有的方法,双向链表的实现,如何维持有序,如何自定义一个特定大小的LinkedHashMap

3万+

LinkedHashMap

一、基础概念 下图很好地还原了LinkedHashMap的原貌:HashMap和双向链表的密切配合和分工合作造就了LinkedHashMap。特别需要注意的是,next用于维护HashMap各个桶中的Entry链,before、after用于维护LinkedHashMap的双向链表,虽然它们的作用对象都是Entry,但是各自分离,是两码事儿。 LinkedHashMap的继承结构如图: HashMap与LinkedHashMap的Entry结构示意图如下图所示 1.遍历 LinkedHashMap进行

sinat_34814635的博客 604

KEPServerEX与三菱iQ-R系列PLC通讯

KEPServerEX与三菱iQ-R系列PLC通讯Mitsubishi Ethernet北京东方鼎晨科技有限公司目 录1. 前言2. 三菱PLC端相关设置3. Kepware端相关设置KEPServerEX是美国PTC Kepware公司生产的具有行业性的连接平台,KEPServerEX支持150多种通讯协议,用于向您的所有应用程序提供单一来源的工业自动化数据。该平台的设计使用户能够通过一个直观的用户界面来连接、管理、监视和控制不同的自动化设备和软件应用程序。KEPServerEX利用OPC(自动化产业的互

qq_28768521的博客 8095

LinkedHashMap源码及LRU实现原理

基本认识 LinkedHashMap位于java.util包,于JDK1.4引入,属于Java Collections Framework的成员。查看其UML关系如下图所示: HashMap在很多场景下都满足K-V的存取,而且在非多线程的场景下也能保持不错的性能,但是HashMap有一个缺点就是不能保证元素的顺序,相比之下,LinkedHashMap就满足了这点,可以保证元素的插入顺序。 Lin...

starsray的博客 1363

最新虚拟串口 Virtual Serial Port Driver V11.0.1068 已经汉化

Virtual Serial Port Driver 11.0.1047 是一款功能强大的虚拟串口驱动程序,专为需要在开发和测试环境中模拟物理串口连接的用户设计。该版本于2023年4月5日发布,主要修复了在导入无效的COM端口捆绑设置时导致的崩溃问题,并优化了软件的自动更新功能。通过使用Virtual Serial Port Driver,用户可以在不依赖物理硬件的情况下,轻松创建和管理虚拟串口,极大地提高了开发和测试的效率。

中游鱼的博客 3万+

使用KITTI数据集测试不同算法的性能

该文章将使用同一个kitti数据集来测试不同算法的性能,目前已经测试的算法包括:LIO-SAM,FAST-LIO2,Point-LIO,Faster-LIO。

wwtx的博客 2586

Java集合类(六)——LinkedHashMap、LRU

LinkedHashMap、LRU 概述 LinkedHashMap继承于HashMap,在HashMap的基础上,新增了两个特性: 支持以节点的插入顺序来迭代该map内的所有节点; 支持缓存设计中LRU的特性,即LinkedHashMap支持按访问顺序来排序节点,具体在内部实现为如果开启了这个特性,则每次通过get方法访问了一个节点,则该节点会被移动到内部的双向链表的末尾,故双向链表的头...

wanger61的博客 434

华为OD机试 - 最佳对手(Python/JS/C/C++ 2025 A卷 200分)

本专栏收录于《华为OD机试真题(Python/JS/C/C++)》。刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新。游戏里面,队伍通过匹配实力相近的对手进行对战。但是如果匹配的队伍实力相差太大,对于双方游戏体验都不会太好。给定n个队伍的实力值,对其进行两两实力匹配,两支队伍实例差距在允许的最大差距d内,则可以匹配。要求在匹配队伍最多的情况下,匹配出的各组实力差

学Java,找哪吒 1379

LinkedHashMap实现LRU

前言: LinkedHashMap是HashMap的子类,在原有HashMap数据结构的基础上,它还维护着一个双向链表链接所有entry,这个链表定义了迭代顺序,通常是数据插入的顺序。 上图我只画了链表,其实红黑树节点也是一样的,只是节点类型不一样而已 也就是说我们遍历LinkedHashMap的时候,是从head指针指向的节点开始遍历,一直到tail指向的节点。 源码 public class LinkedHashMap<K,V> extends HashMap<K,V> imp

张井天的博客 2469

YOLOv8改进-利用图像去雾网络UnfogNet提升检测精度的探索【附核心模块代码】

YOLOv8-UnfogNet联合模型的提出为目标检测和图像去雾领域提供了一个新的思路。通过将图像去雾网络和目标检测网络结合,不仅可以提升在恶劣天气下的目标检测精度,还能够为实际应用中的自动驾驶、监控安防等领域带来更强的鲁棒性和适应性。随着去雾技术和目标检测算法的不断发展,我们相信,这种联合方法将在多个领域中获得更加广泛的应用,并为进一步提升图像质量和检测精度做出重要贡献。

一键难忘的博客 3202

RK3568平台开发系列讲解(NPU篇)什么是RKNPU

📢本篇章将介绍RKNPU。

内核笔记 4354

LinkedHashMap实现LRU算法

LinkedHashMap实现LRU算法

Knight 1279

2025年数学建模国赛高教社杯A题、B题、C题、D题、E题详细思路和代码 模型||插值与拟合

核心思想:构造一个精确通过所有已知离散数据点(xi, yi)的函数y = f(x),并以此函数来估算或预测未知点的值。基本假设:我们认为已知的数据点是100%精确、无误差的(或者误差可忽略不计),比如理论计算值、高精度仪器测量值等。我们的目标是“还原”或“重建”出点与点之间的真实函数关系。关键特征精确性:曲线或曲面必须穿过每一个样本点。局部性:插值结果严重依赖于局部数据点的分布和数值。用途:用于“补全”数据、填充缺失值、进行函数近似等。常见方法多项式插值:拉格朗日插值、牛顿插值。

2201_76125261的博客 802

LinkedHashMap 全面深度解析

LinkedHashMap是HashMap的子类,在哈希表高效存取的基础上,通过双向链表维护元素顺序,支持插入顺序或访问顺序遍历。其核心在于Entry节点扩展了before/after指针,形成独立于哈希桶的双向链表。accessOrder参数控制两种模式:插入顺序保持put顺序,访问顺序则在get/put时移动元素至链表尾部实现LRU策略。通过重写removeEldestEntry方法可轻松实现LRU缓存,在O(1)时间复杂度下平衡了性能与有序性,适用于缓存、日志等场景。

csdn_silent的博客 2014

K8s(二十一):在 Kubernetes 集群中部署 MySQL8.0 高可用集群(1主2从)

🔴 K8s(二十一):在 Kubernetes 集群中部署 MySQL8.0 高可用集群(1主2从)

✨ 欢迎来到【Seal ^_^ 的优快云博客】!✨ 3万+

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

Java LinkedHashMap深度解析:有序HashMap + LRU缓存的完美融合!

是HashMap的子类,在HashMap的基础上额外维护了一个双向链表,用于保存元素的插入顺序或访问顺序,支持有序遍历。序号要点①继承自HashMap,拥有O(1)的快速查找能力②额外维护双向链表,保证元素顺序③两种顺序模式:插入顺序(默认)、访问顺序(accessOrder=true)④轻松实现LRU缓存⑤非线程安全,并发场景需包装⑥内存略大于HashMap(多了前后指针)是 Java 集合框架中的一颗璀璨明珠——它巧妙地将HashMap的O(1) 查找效率与双向链表的顺序性。

✨ 欢迎来到【Seal ^_^ 的优快云博客】!✨ 317

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

JAVA 集合框架进阶:Map 接口的深度解析与实战

本文深入解析Java集合框架中的Map接口,重点讲解HashMap、LinkedHashMap和TreeMap的实现原理与使用场景。Map接口通过键值对(Key-Value)存储数据,Key具有唯一性。文章详细介绍了Map的核心方法、三种遍历方式,并指出entrySet遍历效率最高。针对HashMap,剖析了JDK8中的"数组+链表+红黑树"底层结构,解释了哈希冲突处理机制和扩容原理。通过代码示例演示了HashMap的基本操作,并强调自定义对象作为Key时必须重写hashCode()和e

今天比昨天更努力一点! 3万+

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

深入剖析Java LinkedHashMap:原理、源码与LRU缓存实现

在Java集合框架中,LinkedHashMap作为一个既能快速存取又能保持元素顺序的Map实现,无疑是开发者们的得力助手。本文将带你深入剖析其内部机制。

一起探索IT的世界 1382

Java集合框架进阶:Map 实现类深度解析与实战优化

本文深入解析Java集合框架中的Map接口及其核心实现类,重点剖析HashMap、LinkedHashMap、TreeMap和Hashtable的底层原理与特性。主要内容包括:Map接口的键值对存储特性与核心方法;HashMap的"数组+链表+红黑树"底层结构、哈希冲突处理机制和扩容原理;不同Map实现类在有序性、线程安全和性能方面的对比;以及如何根据业务场景选择合适的Map实现类。文章通过源码分析详细讲解put/get/remove等核心操作的执行流程,并强调哈希值计算、负载因子、树化

今天比昨天更努力一点! 1万+

java基础:Java 深度解析:LinkedHashMap 的设计与实战

LinkedHashMap 是 HashMap 的子类,在哈希表基础上通过双向链表维护了键值对的插入顺序或访问顺序,实现了"有序哈希"的特性。其核心结构包含:fill:#333;color:#333;color:#333;fill:none;哈希表: Nodetable双向链表: 头节点 head + 尾节点 tail继承HashMap.Node增加before/after指针按插入/访问顺序串联节点与 HashMap 相比,LinkedHashMap 重写了newNode()

weixin_43290370的博客 1266

HashMap与LinkedHashMap深度解析:从数据结构到LRU缓存实现

在Java集合框架中,哈希表是实现高效键值对存储的核心数据结构,它通过哈希函数将键映射到数组索引,实现O(1)时间复杂度的快速查找。然而,标准哈希表不保证元素的遍历顺序,这在需要维护插入或访问时序的场景中成为限制。LinkedHashMap在继承HashMap哈希表结构的基础上,通过维护一个贯穿所有节点的双向链表,提供了可预测的迭代顺序,支持插入顺序或访问顺序两种模式。这一特性在需要记录操作序列、保持配置顺序或实现缓存淘汰策略时具有重要技术价值。特别是在构建LRU(最近最少使用)缓存时,LinkedHash

weixin_33895516的博客 574

HashMap与LinkedHashMap深度解析:从无序哈希到有序链表的原理与实战选择

在Java集合框架中,Map是存储键值对的核心数据结构,其设计直接关系到数据存取的效率与顺序特性。HashMap作为最常用的实现,基于哈希表原理,通过数组与链表(或红黑树)的组合,实现了平均O(1)时间复杂度的快速查找、插入与删除。然而,其元素遍历顺序由键的哈希值及桶数组下标决定,并不稳定,无法满足需要保持插入或访问顺序的业务场景。为此,LinkedHashMap在继承HashMap高效哈希能力的基础上,通过维护一条贯穿所有节点的双向链表,提供了可预测的迭代顺序。这一设计在需要记录操作流水(如订单日志)、实

weixin_33841503的博客 424

Java 集合框架进阶——Map 实现类深度解析与实战优化

本文深入解析Java集合框架中的Map接口及其实现类。主要内容包括:Map接口的设计理念与核心特性,重点分析HashMap、LinkedHashMap、TreeMap和Hashtable的底层实现机制;详细讲解HashMap的哈希表结构(数组+链表+红黑树)、扩容机制与键去重原理;比较不同Map实现类的性能差异与适用场景;提供Map集合的遍历优化、内存优化等实用技巧。通过源码解析揭示Map核心方法的实现逻辑,帮助开发者根据业务需求选择最合适的Map实现类,并解决常见的使用问题。

今天比昨天更努力一点! 9164

LinkedHashMap有序性深度解析(20年架构师亲授核心实现细节)

掌握Java集合LinkedHashMap有序性原理,深入解析其双向链表与哈希表结合机制,揭示插入顺序与访问顺序的实现细节。适用于缓存设计、数据排序等场景,核心方法如accessOrder配置与迭代性能优化。架构师亲授实战经验,值得收藏。

ByteChat的博客 948

LinkedHashMap与HashMap深度对比教程:从原理到实践

在Java集合框架中,Map接口是用于存储键值对的核心接口。HashMap和LinkedHashMap都是Map接口的重要实现类,它们在实际开发中应用广泛,但设计理念和使用场景有所不同。​​Java 1.2​​:引入了集合框架,包括HashMap​​Java 1.4​​:LinkedHashMap作为HashMap的子类被引入​​Java 8​​:HashMap引入了红黑树优化链表结构​​Java 后续版本​​:持续的性能优化和内存改进@Override@Override。

Rysxt_的博客 1012

Java面试必备:手把手教你用LinkedHashMap实现LRU缓存(附避坑指南)

本文深入解析了如何利用Java中的LinkedHashMap实现一个工业级的LRU缓存。文章从核心原理出发,详细剖析了LinkedHashMap通过哈希表与双向链表维护访问顺序的机制,并提供了基础实现、线程安全增强版以及生产环境中的性能优化与避坑指南,是Java面试和项目实践的必备参考。

time3的博客 654
上一篇: 集合(三):ArrayList 深度剖析——动态扩容与数据拷贝的艺术
下一篇: 并发编程(三):深度解析Volatile 与 Java 内存模型 (JMM)
TracyCoder123
博客等级 码龄8年 1万+粉丝 226原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TracyCoder123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值