使用LinekedHashMap实现LRU笔记

  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);
 */

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值