一个优雅的LRU缓存 Java 实现

news/2025/2/22 23:19:55/文章来源:https://www.cnblogs.com/ZGByoyo/p/18731623

Java 实现 LRU缓存

LRU算法是一种常用的缓存算法,用于移除最近最少使用的数据。LRU缓存的核心思想是:当缓存容量已满,且需要插入新数据时,优先移除最近最少使用的数据。这种算法在许多场景下都非常有用,比如数据库缓存、网页缓存等。它可以帮助我们高效地管理有限的存储空间,同时保证最近访问的数据能够快速获取。

实现思路

为了实现一个高效的LRU缓存,我们需要结合两种数据结构:哈希表和双向链表。

  • 哈希表:用于快速定位缓存中的数据。通过键(key)可以快速找到对应的节点。
  • 双向链表:用于维护数据的访问顺序。最近访问的节点会被移动到链表的头部,而最久未访问的节点则位于链表的尾部。

这种结合方式的优势在于:

  • 哈希表提供了快速的查找能力,时间复杂度为O(1)。
  • 双向链表可以方便地移动节点,同时维护访问顺序。

以下是LRU缓存的完整实现代码:

public class LRUCache {private int capacity; // 缓存容量private Map<Integer, Node> map; // 哈希表,用于快速查找private Node head; // 双向链表的头节点private Node tail; // 双向链表的尾节点/*** 构造函数,初始化属性字段。虚拟的头节点head和尾节点tail可以简化链表操作。*/public LRUCache(int capacity) {this.capacity = capacity;map = new HashMap<>();head = new Node();tail = new Node();head.next = tail;tail.prev = head;}/*** 如果键存在于哈希表中,获取对应的节点,并将其移动到链表头部。如果键不存在,返回-1。*/public int get(int key) {if(map.containsKey(key)){Node node = map.get(key);move2First(node);return node.val;}return -1;}/*** 如果键已存在,更新节点的值,并将其移动到链表头部。* 如果键不存在,检查缓存是否已满:*  如果未满,创建新节点并插入。*  如果已满,移除链表尾部的节点(最久未访问的节点),并用新节点替换。*/public void put(int key, int value) {if(map.containsKey(key)){Node node = map.get(key);node.val = value;move2First(node);}else{Node node;if(map.size() < capacity) node = new Node(key, value);else{node = tail.prev;map.remove(node.key);node.val = value;node.key = key;}map.put(key, node);move2First(node);}}/*** 将节点移动到链表头部*/public void move2First(Node node){if(node == head.next) return;if(node.next != null) node.prev.next = node.next;if(node.prev != null) node.next.prev = node.prev;head.next.prev = node;node.next = head.next;node.prev = head;head.next = node;}// 测试案例public static void main(String[] args) {LRUCache cache = new LRUCache(2); // 缓存容量为2cache.put(1, 1);cache.put(2, 2);System.out.println(cache.get(1)); // 返回1cache.put(3, 3); // 移除键2System.out.println(cache.get(2)); // 返回-1(键2已被移除)cache.put(4, 4); // 移除键1System.out.println(cache.get(1)); // 返回-1(键1已被移除)System.out.println(cache.get(3)); // 返回3System.out.println(cache.get(4)); // 返回4}}// 双向链表节点
class Node{Node next;Node prev;int val;int key;Node(){ }Node(int key, int val){this.val = val;this.key = key;}
}

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

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

相关文章

final关键字、Object类

1.规则 被final修饰的变量,名称都要大写,多单词的名称则需_来分隔1.修饰方法method方法已经不能被重写了,因为修饰该方法的是final2.修饰类 当一个类中所有的成员方法都不想被重写时,可以直接在类上加上final,无需再一个一个写在方法上2.object类: 是所有类的祖宗,每一个…

Java要记-持续补充中

1. ArrayList操作自定义对象进行removeAll()时,移除失效原因 由于底层最用调用的是Object的equals()方法进行比较的,比较的是地址,两个对象地址当然是不同的了,移除自然会失败。解决方案:重写equals方法。【注意重写equals方法记得也要重写hashCode方法】同时:retainAll(…

this和super--java进阶day01

1.this和super的代表super是父类的标识符,如堆内存中的标志 2.this和super的访问重点说访问构造方法,super()访问父类构造方法我们已经清楚,但是this()访问本类构造方法,我们不清楚有什么用意义 如以下情境 假设在公司制作一个系统,1.0有三位角色随着版本更新,1.1要新…

软件开发与创新课程设计第一次作业---小游戏《勇者冒险》改写

《勇者冒险》小游戏代码优化 一、项目名称与来源 题目为《勇者冒险》(原项目没有名字,是作者取的),代码来源是CSDN,链接如下: https://blog.csdn.net/zjx120307/article/details/126221342?sharetype=blog&shareId=126221342&sharerefer=APP&sharefrom=qq 本…

多周期处理器debug记录

这篇随笔记录的是从普通的多周期处理器到加入握手信号和axi-lite协议sram的处理器。 在之前的多周期处理器里,由于结构比较简单,所以我给ifu和exu的握手信号加入的是时序逻辑,idu由于只做解码,所以握手信号放在了组合逻辑里,差不多就和透传差不多。但是加入sram握手信号以…

继承内存图--java进阶 day01

主方法进栈,有new进堆堆内存中先存自己类中有的变量又因为继承了父类,所以父类中的变量也要存入 即使被私有化,依旧可以继承,只是没有权限使用!创建对象时,会调用构造方法,所以走构造方法,实参传形参.....继续走到super,访问父类的构造方法,父类构造方法进栈,形参继…

离散化学习笔记

离散化学习笔记 OP:又是一如既往的周更。。。水死了 定义离散化:将数字映射为是第几小的数,其保证数据在Hash之后仍然保持原来的全/偏序关系,能够解决:通过元素相对大小即可解决的问题。 其实本质上就是哈希的一种特殊规则而已。(离散化简化了不止亿点)目标将一堆乱序且…

java知识面试day2

1.说出java和c++的区别java是一个纯粹的面向对象语言,所有的对象都继承于java. lang.Object,C++兼容C,不但支持面向对象也支持面向过程 java有着一次编译四处运行的跨平台特性。 java不具有指针,但具有垃圾回收。 java不支持多重继承,只能通过实现多个接口去达到相同目的2.…

继承中构造方法访问特点--java 进阶day01

1.子类不可以继承父类的构造方法构造方法的名称必须与类名一致,上图中类名是Zi,而构造方法名是Fu,肯定不行 2.子类在初始化之前,需要对父类初始化 子类在初始化的过程中,很有可能会调用到父类的数据,如果父类没有提前初始化,子类就无法调用这些数据3.通过在子类中访问父…

Mysql莫名其妙爆出拒绝访问问题的原因及解决方案

本文记录使用Mysql作为数据库时发生拒绝访问问题的解决方案Mysql出现拒绝连接问题 ⛄问题原因 : Mysql密码错误,本机上并不是只有一个Mysql服务,我们在开机时启动了并非以前使用的那个Mysql服务,所以造成了密码的错误🌟解决方案 :手动关闭当前正在启用的Mysql服务,尝试找…

Codes 开源 免费 研发项目管理平台 3.0.0 版本发布及创新的轻IPD实现

Codes 是国内首款重新定义 SaaS 模式的开源项目管理平台,支持云端认证、本地部署、全部功能开放,并且对 30 人以下团队免费。它通过创新的方式简化研发协同工作,使敏捷开发更易于实施。采用轻量化的 IPD 模式实现,且融合了敏捷 。轻 IPD 主要解决多项目交付的研发过程管理,…