用 Java 自己实现一个 LRU

本文介绍了一种经典的缓存淘汰策略LRU(最近最少使用),并提供了基于Java的实现方案,利用双向链表和HashMap数据结构来实现高效的数据访问与更新。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

LRU(Least Recently Used:最近最少使用):简单的说,就是保证基本的 Cache容量,如果超过容量则必须丢掉最不常用的缓存数据,再添加最新的缓存。每次读取缓存都会改变缓存的使用时间,将缓存的存在时间重新刷新。其实,就是清理缓冲的一种策略。
我们可以通过双向链表的数据结构实现 LRU Cache,链表头(head)保存最新获取和存储的数据值,链表尾(tail)既为最不常使用的值,当需要清理时,清理链表的 tail 即可,并将前一个元素设置为tail。结构图如下:
img
**Java 代码实现:**1)、通过原理的分析,我们可以维护一个双向链表结构,如下:LRUNode 实体类,主要理解 prev 和 next 属性,结合上面的链表结构图,就可以理解为,当此对象为 3 时 , prev 应指向 2 , next 应指向 4 。此类为下面类的类种类。

 1 /**
 2  * @ClassName:       LRUNode
 3  * @Description:    定义一个链表类,包含head(指针的上一个对象),tail(指针的下一个对象)类种类
 4  * @author:          zzx
 5  * @date:            2019年3月4日        下午10:32:58
 6  */
 7  class LRUNode {
 8     private String key;
 9     private Object value;
10     //当前对象的上一个对象
11     LRUNode prev;
12     //当前对象的下一个对象
13     LRUNode next;
14     
15     /**
16      * @param key  value
17      * @desc 带有参数的构造器 
18      */
19     public LRUNode(String key,Object value) {
20         this.key=key;
21         this.value=value;
22     }
23 }

2)、我们通过 HashMap 实现一个缓存类 LRUCache *,*我们通过逻辑处理,对最少使用的数据进行删除。代码如下:

  1 /**
  2  * @ClassName:       LRUCache
  3  * @Description:    实现 LRU策略 清除缓存(当缓存大小>=指定大小时)
  4  * @author:          zzx
  5  * @date:            2019年3月4日        下午11:42:11
  6  */
  7 public class LRUCache {
  8     private int capacity;
  9     /**
 10      * @desc 用来存储 key 和 LRUNode对象 充当缓存,且 hashmap 中的数据不会自动清理,需要我们手动清理
 11      */
 12     private HashMap<String, LRUNode> hashMap;
 13     
 14     //数据链表 第一个对象
 15     private LRUNode head;
 16     //数据链表 最后一个对象
 17     private LRUNode tail;
 18     
 19     //带参数 capacity 缓存打下的构造器
 20     public LRUCache(int capacity) {
 21         this.capacity=capacity;
 22         //创建对象时,创建一个hashmap 充当缓存
 23         hashMap = new HashMap<String,LRUNode>();
 24     }
 25     /**
 26      * @Description:    向链表中插入数据
 27      * @return:         void   
 28      */
 29     public void set(String key , Object value) {
 30         //通过 key 查询链表中是否存在此对象
 31          LRUNode lruNode = hashMap.get(key);
 32          //缓存中有值时
 33          if(lruNode != null) {
 34              //为key 附新值,替换就值
 35              lruNode.value = value;
 36              //更新链表指针
 37              appendTail(lruNode,false);
 38          //缓存中无值时    
 39          }else {
 40              //新对象
 41              lruNode = new LRUNode(key, value);
 42              //判断 hashMap 是否大于缓存大小
 43              if(hashMap.size() >= capacity) {
 44                  appendTail(tail,true);
 45              }
 46              //存取新值
 47              hashMap.put(key, lruNode);
 48          }
 49          
 50          //将新值设置为 head
 51          setHead(lruNode);
 52     }
 53     
 54     /**
 55      * @Title:             appendTail
 56      * @Description:     更新链表的前后指针,新增数据公用
 57      */
 58     public void appendTail(LRUNode lNode,boolean flag) {
 59         //存在上一个对象 prev
 60         if(lNode.prev != null) {
 61             //当前对象的上一个对象指向,当前对象的下一个对象。例如:2<-3(当前对象)->4 更新后: 2——>4
 62             lNode.prev.next = lNode.next;
 63         //如果不存在,下一个对象为 head 对象(暂不考虑更改对象)
 64         }else {
 65             head=lNode.next;
 66         }
 67         
 68         //存在下一个对象 next
 69         if(lNode.next != null) {
 70             // 4——>2
 71             lNode.next.prev=lNode.prev;
 72         }else {
 73             //如果当前对象是最后一个对象,则上一个对象就为最后一个对象
 74             tail=lNode.prev;
 75         }
 76         
 77         lNode.prev=null;
 78         lNode.next=null;
 79         //如果内存不足,需要删除tail
 80         if(flag) {
 81             hashMap.remove(lNode.key);
 82         }
 83     }
 84     
 85     /**
 86      * @Title:             setHead
 87      * @Description:     设置链表的 头 节点
 88      * @param:           node   
 89      * @return:         void   
 90      */
 91     public void setHead(LRUNode node) {
 92         if(head != null) {
 93             node.next=head;
 94             head.prev=node;
 95         }
 96         head=node;
 97         if(tail == null) {
 98             tail=node;
 99         }
100     }
101 }
d.prev=node;
 95         }
 96         head=node;
 97         if(tail == null) {
 98             tail=node;
 99         }
100     }
101 }
好的,我可以帮你实现一个Java版的Lru缓存。 Lru(Least Recently Used)缓存是一种常见的缓存策略,它会删除最近最少使用的缓存项。在Java中,我们可以使用LinkedHashMap来实现一个Lru缓存,因为LinkedHashMap本身就是一个有序的Map,而且可以通过覆写removeEldestEntry方法来实现自动删除最近最少使用的缓存项。 以下是一个简单的Java实现: ```java 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) { super(capacity, 0.75f, true); this.capacity = capacity; } @Override public boolean removeEldestEntry(Map.Entry<K, V> eldest) { return size() > capacity; } } ``` 这个LruCache类继承自LinkedHashMap,并覆写了removeEldestEntry方法,当缓存项数量超过capacity时,就会自动删除最近最少使用的缓存项。我们可以使用put方法向缓存中添加缓存项,使用get方法获取缓存项,使用size方法获取缓存项数量。 示例代码: ```java LruCache<String, Integer> cache = new LruCache<>(2); cache.put("a", 1); cache.put("b", 2); System.out.println(cache.get("a")); // 1 cache.put("c", 3); System.out.println(cache.get("b")); // null cache.put("d", 4); System.out.println(cache.get("a")); // null System.out.println(cache.get("c")); // 3 System.out.println(cache.get("d")); // 4 ``` 在上面的示例中,我们创建了一个容量为2的LruCache,向其中添加了三个缓存项,当缓存项数量超过容量时,会自动删除最近最少使用的缓存项,所以最终缓存中只剩下了"c"和"d"。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值