当前位置:

首页 > 编程开发 > 如何在 Java 中使用 LinkedHashMap 的访问顺序模式实现一个基础的 LRU 缓存淘汰

如何在 Java 中使用 LinkedHashMap 的访问顺序模式实现一个基础的 LRU 缓存淘汰

LinkedHashMap设置accessOrder=true后,每次访问将节点移至尾部,链表头部即为最久未用条目。通过继承并重写removeEldestEntry()方法,依据size()>capacity自动淘汰。该实现非线程安全,并发场景需加锁或改用ConcurrentHashMap。不建议存储null值,避免get()返回null时无法区分未命中与空

这部分内容,其实谈到底层原理并不复杂,但能把它用好、用对,才是日常开发中拉开差距的地方。就拿 accessOrder=true 这个参数来说,很多开发者知道它能实现LRU,但真要写一个健壮的缓存,里头门道不少。我们一个一个拆开看。

如何在 Ja va 中使用 LinkedHashMap 的访问顺序模式实现一个基础的 LRU 缓存淘汰

为什么 LinkedHashMap 的 accessOrder=true 能支持 LRU

原因很简单。你构造 LinkedHashMap时,把第三个参数设为 true,它内部那条维护顺序的双向链表就不再看“谁先来”,而是看“谁最后被用”。每次你调用 get() 或者 put()(如果是更新已有key),它都会默默把那个节点挪到链表尾部。

这样一来,链表头部就永远蹲着那个“最久没被翻过牌子”的条目。淘汰时,你只需要把头节点干掉就行,效率很高。

需要留意的是,单纯新增一个key时,它只是追加到尾部,不会打乱其他节点的相对顺序。这其中的区别,你写代码的时候得想清楚。

如何重写 removeEldestEntry() 控制缓存容量

容量上限怎么控制?靠一个钩子方法——removeEldestEntry()。它每次 put() 结束后被自动调用,如果返回 true,框架就顺手把链表头(也就是最老的节点)删掉。这是实现容量限制的核心,不是你手动去轮询或者定时清理的。

关键点在于:

  • 你必须继承 LinkedHashMap 然后重写这个方法,直接new出来的实例没法改。
  • 判断逻辑通常就一行:size() > capacity,别在里面写日志、搞IO这些耗时操作,会拖累性能。
  • 这个方法在 put() 内部是同步执行的,你不用额外加锁,但整个缓存仍然需要考虑并发安全。
class LRUCache extends LinkedHashMap {
    private final int capacity;

    LRUCache(int capacity) {
        // accessOrder = true
        super(capacity, 0.75f, true);
        this.capacity = capacity;
    }

    @Override
    protected boolean removeEldestEntry(Map.Entry eldest) {
        return size() > capacity;
    }
}

并发场景下直接用 LinkedHashMap 子类会出什么问题

很多人在这块栽过跟头。LinkedHashMap 本身可不是线程安全的。多线程环境下同时搞 get() 和 put(),链表结构会乱套,甚至死循环(JDK 7/8 时代有经典bug),或者直接抛 ConcurrentModificationException。

为了防杠,有人会直接加个 synchronized,但这招在“读多写少”的场景下直接让你的吞吐量惨不忍睹。用 Collections.synchronizedMap() 包一下呢?有个坑——removeEldestEntry() 并不在同步块里,可能会失效。

更稳妥的做法是:自己拿 ReentrantLock 手动锁住 get() 和 put() 的临界区。当然,如果你愿意放弃 LinkedHashMap 方案,直接用 ConcurrentHashMap 加上自定义的队列,也是条路。

别忽略 get() 返回 null 时的边界行为

缓存里没有key的时候,get() 返回 null,这不会触发链表调整,符合预期。但容易被忽略的是:put(key, null) 是合法的,它会正常参与LRU排序。如果业务允许value为 null,那么 get() 返回 null 时,你就分不清是“没命中”还是“命中了但值为null”。

建议是:

  • 最好别存 null value。可以在 put() 前做校验,发现 null 就直接抛 NullPointerException。
  • 如果非支持不可,可以考虑用 Optional 包装返回值,或者额外维护一个 Set 来记录哪些key已经存在。
  • computeIfAbsent() 这类衍生方法在 accessOrder 模式下同样会触发重排序,但你得小心lambda内部的递归调用,别把自己玩死了。

说到底,accessOrder 模式只是一个高效的链表维护策略,它不帮你解决原子性、可见性、null 语义这些上层问题。它只优雅地做到了:帮你轻松判定“哪个是最近最久没被碰过的”。

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
作者最新文章
编程开发 Java
相关文章 更多
codekit环境配置指南从安装到环境搭建完整教程
codekit环境配置指南从安装到环境搭建完整教程

详解 CodeKit 在 macOS 下的安装步骤、项目导入方法、Sass与JavaScript编译设置及浏览器自动刷新功能,助您快速搭建高效的前端开发环境。

codex安装windows 命令行完整操作教程
codex安装windows 命令行完整操作教程

详解Windows环境下安装OpenAI Codex CLI的步骤,包括WSL环境检查、Node.js/npm配置、npm全局安装命令及首次启动验证,适合开发者快速上手。

NativeRest环境配置要求与完整操作教程
NativeRest环境配置要求与完整操作教程

学习如何配置 NativeRest REST API 客户端。涵盖 Windows/macOS/Linux 安装后的工作区创建、环境变量管理、请求编辑及响应查看步骤,帮助开发者快速完成基础环境搭建与连通性测试。

CSS设置透明度的注意事项有哪些?opacity属性详解
CSS设置透明度的注意事项有哪些?opacity属性详解

深入解析CSS中设置透明度的核心属性opacity,剖析子元素继承、事件穿透、层叠上下文等关键注意事项,并提供与rgba、hsla的实用选型对比。

flutter页面传值到后台的方法及示例代码
flutter页面传值到后台的方法及示例代码

flutter页面传值到后台的完整实现方法及示例代码,帮助读者快速掌握相关技术要点。

Java 8至21新特性代码写法对比:Lambda、Record与Switch
Java 8至21新特性代码写法对比:Lambda、Record与Switch

本文通过具体的旧版与新版代码对比,详细剖析Java 8引入的Lambda表达式、Java 14/16引入的Record类,以及Java 12至21逐步演进完善的Switch表达式与模式匹配,展示代码简化路径与避坑要点。

AI智能体开发培训课程学什么及实战内容介绍
AI智能体开发培训课程学什么及实战内容介绍

系统梳理AI智能体开发培训的核心知识模块、技术栈选型与典型实战项目,解析低代码平台与纯代码框架的差异,提供从零构建可落地智能体的完整学习与实施路径。

Java子类未实现抽象方法编译错误修复指南
Java子类未实现抽象方法编译错误修复指南

针对Java开发中常见的“子类未实现抽象方法”编译错误,深入分析报错原因,提供重写实现、声明抽象子类两种标准修复路径,并总结参数签名、访问修饰符等典型避坑要点。

解决PHP递归报错:max_nesting_level限制与内存溢出处理
解决PHP递归报错:max_nesting_level限制与内存溢出处理

遇到PHP递归报错时,不要盲目调大max_nesting_level。本文教你区分Xdebug限制、内存耗尽和正则递归错误,提供代码级的终止条件优化与迭代替代方案,彻底解决栈溢出问题。

PHP递归中static变量与引用传递的常见陷阱及调试
PHP递归中static变量与引用传递的常见陷阱及调试

本文分析PHP递归中static变量导致的状态污染及引用传递引发的共享数据修改问题。提供具体的代码复现、缓存键设计建议及调试打印技巧,帮助开发者避免隐蔽的逻辑错误。

查看更多
精品专题 更多
装机必备
装机必备

正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

Windows
Windows

正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

macOS软件
macOS软件

正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

Mac软件 更多
Visual Studio Code macOS版
Visual Studio Code macOS版
macOS

Visual Studio Code 是微软提供的免费代码编辑器,支持 macOS,并为 Intel 与 Apple 芯片 Mac 提供适配版本。软件集代码编辑、调试、Git 源代码管理、集成终端和扩展市场于一体。

photoshop
photoshop
Windows、macOS 、 iPad

Photoshop 2026 是 Adobe 推出的专业图像处理与视觉设计软件,支持 Windows、macOS 和 iPad 等平台,广泛应用于摄影修图、电商设计、平面海报、数字绘画及视觉合成等创作场景。

Blender
Blender
Windows、macOS 和 Linux

Blender 是一款免费开源、跨平台的专业 3D 创作软件,集建模、动画、渲染、视频编辑与视觉合成等功能于一体,广泛应用于影视动画、游戏设计和建筑可视化等领域。软件支持 Cycles 物理渲染器与 Eevee 实时渲染引擎,并提供多边形建模、骨骼绑定、物理模拟等专业工具。Blender 兼容 Windows、macOS 和 Linux 系统,安装包轻巧、运行流畅,依托活跃的全球开发者社区持续更新,是从初学者到专业创作者都值得选择的正版 3D 创作工具。

WINDOWS 更多
3dmax(3ds max)
3dmax(3ds max)
Windows

Autodesk 3ds Max 是一款专业的三维建模、动画与渲染软件,广泛应用于建筑可视化、游戏开发、影视动画、广告设计和产品展示等领域。

photoshop
photoshop
Windows、macOS 、 iPad

Photoshop 2026 是 Adobe 推出的专业图像处理与视觉设计软件,支持 Windows、macOS 和 iPad 等平台,广泛应用于摄影修图、电商设计、平面海报、数字绘画及视觉合成等创作场景。

Blender
Blender
Windows、macOS 和 Linux

Blender 是一款免费开源、跨平台的专业 3D 创作软件,集建模、动画、渲染、视频编辑与视觉合成等功能于一体,广泛应用于影视动画、游戏设计和建筑可视化等领域。软件支持 Cycles 物理渲染器与 Eevee 实时渲染引擎,并提供多边形建模、骨骼绑定、物理模拟等专业工具。Blender 兼容 Windows、macOS 和 Linux 系统,安装包轻巧、运行流畅,依托活跃的全球开发者社区持续更新,是从初学者到专业创作者都值得选择的正版 3D 创作工具。