使用LinekedHashMap实现LRU笔记

3 篇文章 0 订阅
3 篇文章 0 订阅
  1. LRU 缓存 - 力扣(LeetCode)

LRU算法设计

cache 这个数据结构必要的条件:

  1. cache 中的元素必须有时序,以区分最近使用和久未使用的数据。当容量满了之后删除最久未使用的元素
  • 如果我们每次默认从链表尾部添加元素,那么显然越靠尾部的元素就是最近使用的,越靠头部的元素就是最久未使用的。
  1. 需要在cache中快速找某个key是否已经存在并得到对应的val
  • 对于某一个 key,我们可以通过哈希表快速定位到链表中的节点,从而取得对应 val
  1. 每次访问cache 中的某个key,需要将这个元素变为最近使用的,也就是说 cache 要支持在任意位置快速插入和删除元素。
  • 链表显然是支持在任意位置快速插入和删除的,改改指针就行。只不过传统的链表无法按照索引快速访问某一个位置的元素,而这里借助哈希表,可以通过 key 快速映射到任意一个链表节点,然后进行插入和删除。
    LRU 缓存算法的核心数据结构就是哈希链表,双向链表和哈希表的结合体。
    在这里插入图片描述

代码实现

LinkedHashMap,它与HashMap的区别就是在Map的结构外还有一个链表结构,Map的每个key-value都会以Node的形式同时存储在Map和链表中
当put一个key和value时,加入Map的同时,也加入链表尾部,这样实现了有序(HashMap本来是无序的)
正是这个链表完成了LRU的实现。

  • get
    (使用了)的时候将该Node从链表中移除,并添加到链表尾部。
  • put
    检查Map的容量,如果超出了,就从移除链表头部Node(时间最久的,即最近最少使用),同时从map中移除。
    在这里插入图片描述
    使用JAVA实现
// 使用LinkedHashMap实现LRU算法
class LRUCache {
    int cap;
    LinkedHashMap<Integer, Integer> cache = new LinkedHashMap<>();

    public LRUCache(int capacity) {
        this.cap = capacity;
    }

    public int get(int key) {
        if(!cache.containsKey(key)){
            return -1;
        }
        // 否则,将key变为最近使用
        makRecently(key);
        return cache.get(key);
    }
    
    public void put(int key, int value) {
        // 如果key已经存在
        if(cache.containsKey(key)){
            // 修改key的值
            cache.put(key, value);
            makRecently(key);
            return;
        }
        // 如果不存在,判断容量满没满,如果已满
        if(cache.size() >= this.cap){
            // 链表头部就是最久未使用的key,删除链表头
            int oldestKey = cache.keySet().iterator().next();
            cache.remove(oldestKey);
        }
        // 将新的key添加到链表尾部
        cache.put(key, value);
    }

    private void makRecently(int key){
        int val = cache.get(key);
        // 删除key,重新插入到队尾
        cache.remove(key);
        cache.put(key, val);
    }
}

/**
 * Your LRUCache object will be instantiated and called as such:
 * LRUCache obj = new LRUCache(capacity);
 * int param_1 = obj.get(key);
 * obj.put(key,value);
 */

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 使用 Java 实现 LRU 算法的基本步骤是:1. 定义一个双向链表;2. 重写put()和get()方法;3. 在put()方法中,如果元素已存在,移动到链表头部;4. 在get()方法中,如果元素存在,移动到链表头部;5. 如果缓存已满,移除链表尾部的元素。 ### 回答2: 使用Java实现lru算法可以通过使用LinkedHashMap实现。 LinkedHashMapHashMap的子类,它通过维护一个双向链表来记录插入顺序。我们可以利用LinkedHashMap的特性来实现lru算法。 具体实现步骤如下: 1. 创建一个继承自LinkedHashMap的子类LRUMap,指定其泛型为<K, V>。 2. 重写LRUMap的构造方法,传入一个capacity参数来指定LRUMap的容量,并调用父类LinkedHashMap的构造方法来初始化LRUMap。 3. 在重写的构造方法中,使用super(capacity, 0.75f, true)来调用父类构造方法,并将最后一个参数设置为true,表示开启访问顺序模式。 4. 重写LRUMap的removeEldestEntry方法,当LRUMap的大小超过指定容量时,移除最老的键值对。 5. 至此,我们已经完成了LRUMap的实现。 下面是一个使用LRUMap的示例: ```java import java.util.LinkedHashMap; public class LRUMap<K, V> extends LinkedHashMap<K, V> { private final int capacity; public LRUMap(int capacity) { super(capacity, 0.75f, true); this.capacity = capacity; } @Override protected boolean removeEldestEntry(Map.Entry<K,V> eldest) { return size() > capacity; } public static void main(String[] args) { LRUMap<String, Integer> lruMap = new LRUMap<>(3); lruMap.put("a", 1); lruMap.put("b", 2); lruMap.put("c", 3); lruMap.put("d", 4); System.out.println(lruMap); // 输出: {b=2, c=3, d=4} } } ``` 以上示例中,我们创建了一个容量为3的LRUMap,并进行了插入操作。当容量超过3时,最老的键值对"a"会被移除,而最新的键值对"d"则会按照访问顺序保存在LRUMap中。最后,我们打印出LRUMap的内容,验证了LRU算法的实现。 ### 回答3: LRU(Least Recently Used,最近最少使用)是一种常见的缓存淘汰算法,其中使用Java实现LRU算法的原理是根据数据的使用情况对缓存中的数据进行淘汰,将最近最少使用的数据移除,以腾出空间存储新的数据。 在Java中,我们可以使用LinkedHashMap实现LRU算法。LinkedHashMapHashMap的子类,它可以保持插入顺序或访问顺序。 下面是一个简单的使用Java实现LRU算法的示例代码: ```java import java.util.LinkedHashMap; import java.util.Map; public class LRUCache<K, V> extends LinkedHashMap<K, V> { private int capacity; // 缓存容量 public LRUCache(int capacity) { super(capacity, 0.75f, true); // 设置访问顺序为true,保持LRU特性 this.capacity = capacity; } @Override protected boolean removeEldestEntry(Map.Entry<K, V> eldest) { return size() > capacity; // 当缓存大小超过容量时,移除最久未使用的数据 } public static void main(String[] args) { 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} cache.put(4, "D"); System.out.println(cache); // 输出:{2=B, 3=C, 4=D} cache.get(2); System.out.println(cache); // 输出:{3=C, 4=D, 2=B} } } ``` 在以上示例代码中,我们继承了LinkedHashMap,并重写了`removeEldestEntry`方法,当缓存大小超过容量时,会自动移除最久未使用的数据。 通过以上代码,我们可以使用Java实现LRU算法,并对缓存中的数据进行淘汰。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值