如何实现 LRU 缓存:基于LinkedHashMap?

全文目录:

    • 开篇语
    • 前言
    • 1. LinkedHashMap 简介
      • 1.1 LinkedHashMap 的构造方法
    • 2. 基于 LinkedHashMap 实现 LRU 缓存
      • 2.1 设计思路
      • 2.2 实现步骤
      • 2.3 代码说明
      • 2.4 测试案例
      • 2.5 解释
    • 3. LRU 缓存优化
      • 3.1 `removeEldestEntry()` 方法的灵活性
      • 3.2 内存管理
    • 4. 总结
    • 文末

开篇语

哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛

  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。

  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。

小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!

前言

在很多实际的应用中,尤其是需要缓存数据的场景下,我们经常会遇到 LRU(Least Recently Used,最近最少使用)缓存。LRU 缓存是通过淘汰最久未使用的缓存数据来节省内存空间。对于高效的 LRU 缓存,我们不仅要保证快速的查找、插入和删除操作,还要能够快速地淘汰最久未使用的元素。

在 Java 中,基于 LinkedHashMap 实现 LRU 缓存是非常简便和高效的,因为 LinkedHashMap 本身提供了按照访问顺序迭代的能力,我们可以利用这一特性轻松实现 LRU 缓存。


1. LinkedHashMap 简介

LinkedHashMapHashMap 的一个子类,它基于哈希表实现,并且维护了插入顺序或访问顺序。这使得 LinkedHashMap 特别适合于实现缓存,尤其是在需要按访问顺序迭代时。

1.1 LinkedHashMap 的构造方法

  • LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder):
    • initialCapacity:初始容量。
    • loadFactor:负载因子。
    • accessOrder:如果设置为 true,则按照访问顺序排序;如果设置为 false,则按照插入顺序排序。

accessOrder 设置为 true 时,LinkedHashMap 会在每次访问(get 或 put 操作)时,将访问的元素移动到链表的末尾。这个特性让我们能够轻松地实现 LRU 缓存。


2. 基于 LinkedHashMap 实现 LRU 缓存

2.1 设计思路

  1. 缓存大小限制:我们需要为缓存设定一个最大容量 capacity,当缓存容量超过该值时,我们就需要淘汰最久未使用的元素。
  2. LRU 淘汰规则:在每次插入或访问元素时,我们将该元素移动到链表的末尾,这样链表的头部始终保存着最久未使用的元素。当缓存容量超过限制时,我们可以直接删除链表头部的元素。
  3. 使用 LinkedHashMap:利用 LinkedHashMapaccessOrder 的特性,结合 removeEldestEntry() 方法来自动删除最久未使用的元素。

2.2 实现步骤

我们可以创建一个继承自 LinkedHashMap 的类,并重写 removeEldestEntry() 方法,该方法会在每次插入新元素时被调用。

import java.util.LinkedHashMap;
import java.util.Map;public class LRUCache<K, V> extends LinkedHashMap<K, V> {private final int capacity;// 构造函数,初始化容量和 accessOrderpublic LRUCache(int capacity) {super(capacity, 0.75f, true);  // 第三个参数 true 表示按访问顺序排序this.capacity = capacity;}// 重写 removeEldestEntry 方法,当缓存容量超出时,移除最久未使用的条目@Overrideprotected boolean removeEldestEntry(Map.Entry<K, V> eldest) {return size() > capacity;}// 获取缓存中的值public V get(K key) {return super.getOrDefault(key, null);}// 插入缓存值public void put(K key, V value) {super.put(key, value);}
}

2.3 代码说明

  • LRUCache 类继承自 LinkedHashMap,并通过构造函数设置了 accessOrdertrue,这使得每次访问元素时,该元素都会被移到链表的末尾。
  • removeEldestEntry() 方法会在每次插入新元素时检查缓存的大小。如果缓存的大小超过了设定的容量,它会返回 true,从而自动移除最久未使用的元素。
  • get(K key)put(K key, V value) 方法分别用于获取和插入缓存中的数据。

2.4 测试案例

public class Main {public static void main(String[] args) {// 创建一个容量为 3 的 LRU 缓存LRUCache<Integer, String> cache = new LRUCache<>(3);// 向缓存中插入数据cache.put(1, "A");cache.put(2, "B");cache.put(3, "C");// 打印缓存内容System.out.println(cache); // 输出: {1=A, 2=B, 3=C}// 访问元素 1cache.get(1); // 使元素 1 最近访问// 插入新的元素,此时缓存超过容量,元素 2 将被移除cache.put(4, "D");// 打印缓存内容System.out.println(cache); // 输出: {3=C, 1=A, 4=D}}
}

输出:

{1=A, 2=B, 3=C}
{3=C, 1=A, 4=D}

2.5 解释

  1. 初始时,缓存的容量为 3,元素 {1=A, 2=B, 3=C} 被插入缓存。
  2. 当访问 get(1) 时,元素 1 被移动到链表的末尾。
  3. 当插入元素 4=D 时,由于缓存已经满了,元素 2(最久未访问)被自动删除,最终缓存内容为 {3=C, 1=A, 4=D}

3. LRU 缓存优化

3.1 removeEldestEntry() 方法的灵活性

通过 removeEldestEntry() 方法,我们可以根据不同的需求定制缓存的淘汰规则。例如,我们可以根据某些条件(如元素的大小、元素的过期时间等)来决定是否删除最久未使用的元素。

3.2 内存管理

虽然 LinkedHashMapaccessOrder 特性和 removeEldestEntry() 方法让我们能够很方便地实现 LRU 缓存,但也需要注意缓存大小和内存使用的平衡。特别是当缓存需要存储大量数据时,合理设置缓存容量和定期清理缓存非常重要。


4. 总结

  • 使用 LinkedHashMap 实现 LRU 缓存的方式简洁高效,特别适合需要按访问顺序管理缓存数据的场景。
  • 通过重写 removeEldestEntry() 方法,我们能够在缓存超出容量时自动移除最久未使用的元素。
  • 这种方法不仅具有较高的性能,还能避免重复的复杂操作,方便开发者实现高效的缓存管理。

LRU 缓存的实现,帮助我们在高效处理数据时保持内存的合理使用,避免内存溢出或缓存过期问题的出现。

… …

文末

好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。

… …

学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!

wished for you successed !!!


⭐️若喜欢我,就请关注我叭。

⭐️若对您有用,就请点赞叭。
⭐️若有疑问,就请评论留言告诉我叭。


版权声明:本文由作者原创,转载请注明出处,谢谢支持!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/pingmian/82747.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Boot测试框架全面解析

Spring Boot测试框架基础 Spring Boot通过增强Spring测试框架的能力,为开发者提供了一系列简化测试流程的新注解和特性。该框架建立在成熟的Spring测试基础之上,通过自动化配置和专用注解显著提升了测试效率。 核心依赖配置 要使用Spring Boot的全部测试功能,只需在项目中…

Spring Boot 整合 Spring Data JPA、strategy 的策略区别、什么是 Spring Data JPA

DAY29.2 Java核心基础 Spring Boot 整合 Spring Data JPA Spring Data JPA根据具体的数据库分为不同的子模块&#xff0c;无论是关系型数据库和非关系型数据库&#xff0c;Spring Data都提供了支持 Mysql&#xff1a;Spring Data JPA Redis&#xff1a;Spring Data Redis …

Ubuntu 服务器配置与 Cloudflare Tunnel 部署指南 免费内网穿透家用服务器

Ubuntu 服务器配置与 Cloudflare Tunnel 部署指南 本文档总结了服务器配置相关内容&#xff0c;包括 Ubuntu 服务器配置、硬盘扩容、静态 IP 设置以及 Cloudflare Tunnel 的部署步骤。 目录 硬盘分区与扩容设置静态 IPCloudflare Tunnel 部署SSH 通过 Cloudflare Tunnel常见…

降低实验检测报告编制耗时 质检LIMS系统的应用策略

在质检工作流程中&#xff0c;检测报告编制往往是耗时耗力的关键环节。传统人工编制报告不仅效率低下&#xff0c;还容易出现数据错误、格式不统一等问题。质检 LIMS 系统凭借其强大的自动化、智能化功能&#xff0c;为检测报告编制带来革命性变革&#xff0c;能够将编制时间减…

同为.net/C#的跨平台运行时的mono和.net Core有什么区别?

Mono 和 .NET Core&#xff08;现已统一为 .NET&#xff09;都是 .NET 生态的跨平台实现&#xff0c;但它们在设计目标、技术特性和应用场景上有显著区别。以下是详细对比&#xff1a; ​​1. 历史背景​​ ​​项目​​​​诞生时间​​​​开发者​​​​当前状态​​​​Mo…

Android AIDL Hal最低保证出现的问题

1. AIDL HAL 的“最低保证”特性 &#xff08;1&#xff09;协议层级的强制支持 在 IComposer AIDL 接口定义中&#xff08;如 android.hardware.graphics.composer3&#xff09;&#xff0c;Google 已经将部分功能列为 必须支持的特性&#xff08;MUST&#xff09;。例如&am…

苹果FINDMY和谷歌FIND HUB增强共享位置功能

近期&#xff0c;苹果Findmy增强了追踪和分享丢失物品位置方面的功能&#xff0c;“共享物品位置”&#xff0c;用户可以安全地与航空a公司等第三方分享丢失物品的位置&#xff0c;以便于行李找回。 iOS 18.2的这一新功能使用户可以轻松、安全地与航空公司等第三方分享AirTag或…

基于GA遗传优化的FIR滤波器幅频相频均衡补偿算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 在数字信号处理领域&#xff0c;有限冲激响应&#xff08;FIR&#xff09;滤波器因其结构简单、稳定性好且易于实现线性相位等优点被广泛应用。然而&#xff0c;实…

双路物理CPU机器上安装Ubuntu并部署KVM以实现系统多开

在双路物理CPU机器上安装Ubuntu并部署KVM以实现系统多开&#xff0c;并追求性能最优&#xff0c;需要从硬件、宿主机系统、KVM配置、虚拟机配置等多个层面进行优化。 以下是详细的操作指南和优化建议&#xff1a; 阶段一&#xff1a;BIOS/UEFI 设置优化 (重启进入) 启用虚拟化…

adb查看、设置cpu相关信息

查内存 adb shell dumpsys meminfo查CPU top -m 10打开 system_monitor adb shell am start -n eu.chainfire.perfmon/.LaunchActivity设置CPU的核心数 在/sys/devices/system/cpu目录下可以看到你的CPU有几个核心&#xff0c;如果是双核&#xff0c;就是cpu0和cpu1&#xff0c…

【Unity基础】Unity新手实战教程:用ScriptableObject控制Cube颜色

目录 项目概述&#x1f6e0;️ 完整操作步骤&#xff08;10分钟内完成&#xff09;步骤1&#xff1a;创建ScriptableObject类步骤2&#xff1a;创建颜色配置资产步骤3&#xff1a;创建Cube控制器步骤4&#xff1a;设置场景和Cube步骤5&#xff1a;添加简单UI提示步骤6&#xff…

One Year~

入局 作为科班学生&#xff0c;没事就在CSDN闲逛&#xff0c;只作为旁观者的身份去体会别人的好文。当时也没想着说去自己写一些博客记录学习过程。相信大多数同学和我有一样的心理。 但在看鱼皮哥的课程时&#xff0c;发现他有着写文档和博客的习惯&#xff0c;整理自己的思路…

【Redis】第3节|深入理解Redis线程模型

一、Redis基础认知 &#xff08;一&#xff09;定义与定位 Redis&#xff08;Remote Dictionary Server&#xff09;是开源高性能键值数据库&#xff0c;核心特点如下&#xff1a; 数据结构丰富&#xff1a;支持字符串、哈希、列表、集合、有序集合等复杂数据类型&#xff0…

vben-admin 2.8.0 版本修改 axios响应处理逻辑

此前端框架下的 Axios 在后端返回的结果老是无法正常解析&#xff0c;找到他源码的封装类&#xff0c;修正这个问题 文件位于 src\utils\http\axios\index.ts 修改前 transformResponseHook: (res: AxiosResponse<Result>, options: RequestOptions) > {const { t }…

深入理解JavaScript设计模式之原型模式

目录 前言引入原型模式头脑风暴传统方式 vs 原型模式实战案例&#xff1a;飞机大战中的分身术 原型模式实现的关键秘密实战演练&#xff1a;造一架能分身的飞机克隆是创建对象的手段原型模式&#xff1a;轻装上阵的造物术 原型编程范型的一些规则原型编程的四大门规&#xff1a…

【数据库】概述(纯理论)

数据库系统引论 数据管理系统的发展 数据管理&#xff1a;对数据分类、组织、编码、存储、检索、维护 发展&#xff1a;人工管理、文件系统、数据库系统 40-50年代 人工管理 数据不保存&#xff0c;没有专门软件管理数据&#xff0c;应用程序完全依赖于数据&#xff0c;数据…

语音合成之十七 语音合成(TTS)中文自然度:问题、成因、解决方案

语音合成&#xff08;TTS&#xff09;中文自然度&#xff1a;问题、成因、解决方案 中文TTS系统基本架构中文TTS常见问题深度剖析与解决方案音色跳变成因分析解决方案 声调与重读错误成因分析业界解决方案 漏读与断句错误成因分析业界解决方案 在跨语言TTS系统比较中&#xff0…

我在 Linux 进程管理中踩过的坑:僵尸、瞬时与不可中断进程实战实录

作为运维老鸟&#xff0c;我曾在 Linux 进程管理上栽过不少跟头。记得第一次遇到满屏僵尸进程时&#xff0c;服务器直接卡到连 SSH 都登不上&#xff0c;看着ps命令里一排排刺眼的Z状态进程&#xff0c;手心直冒冷汗。后来又碰到过瞬时进程搞崩日志系统&#xff0c;明明监控显示…

【设计模式】简单工厂模式,工厂模式,抽象工厂模式,单例,代理,go案例区分总结

工厂模式三种类型&#xff1a; 一、简单工厂模式&#xff08;Simple Factory&#xff09; 定义&#xff1a; 用一个工厂类&#xff0c;根据传入的参数决定创建哪一种具体产品类实例。 面试说法&#xff1a; 由一个统一的工厂创建所有对象&#xff0c;增加新产品时需要修改工…

某标杆房企BI平台2.0升级实践

当房地产行业从“规模竞赛”转向“精益运营”&#xff0c;数字化转型成为破局关键。某千亿房企携手亿信华辰&#xff0c;以“用数据重构业务价值链”为目标&#xff0c;历经6个月完成BI平台战略性升级。在这场从“数据可视化”到“决策智能化”的跃迁中&#xff0c;亿信华辰ABI…