【40讲系列15】LRU缓存

一、理论

LRU是一种缓存淘汰策略,最近使用的认为是「有用的」,很久没使用过的数据认为是无用的,缓存满时就优先删除它们。

  • LRU- Least recently used(最近最少使用页面置换算法、按访问的时序来淘汰)
  • LFU- Least frequently used(最近最不常用页面置换算法、按访问频率来淘汰)

LRU缓存算法的核心数据结构:哈希表 + 双向链表

设计的cache需要满足的条件:O(1)查询、O(1)修改、有顺序之分。

哈希表查找快,无序;链表有序,但查找慢。所以结合一下,哈希+链表,借助哈希表赋予链表快速查找的特性。

二、典型例题

☆☆①:设计和实现一个LRU缓存机制(LC146)

方法1:使用LinkedHashMap。属于取巧,面试不大行。。

方法2:HashMap + 手写DoubleList。

方法1:(需要理解LinkedHashMap的源码)

LinkedHashMap的有序可以按两种顺序排列,一种是按照插入的顺序,一种是按照读取的顺序。其内部是靠 建立一个双向链表 来维护这个顺序的。

构造函数:主要是两个构造方法,一个继承HashMap,一个是可选择accessOrder的值(默认false,代表按照插入顺序排序)来确定是按插入顺序还是读取顺序排序。

class LRUCache extends LinkedHashMap<Integer,Integer> {
    /**
     * LinkedHashMap的构造函数之一。
     * 这里的 accessOrder 默认是为false,如果要按读取顺序排序需要将其设为 true
     * initialCapacity 代表 map 的 容量,loadFactor 代表加载因子 (默认即可)
     *     public LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) {
     *         super(initialCapacity, loadFactor);
     *         this.accessOrder = accessOrder;
     *     }
     */
    private int capacity;
    public LRUCache(int capacity) {
        super(capacity,0.75f,true);
        this.capacity = capacity;
    }
    public int get(int key) {
        return super.getOrDefault(key, -1);
    }
    public void put(int key, int value) {
        super.put(key,value);
    }
    @Override
    protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) {
        return size() > capacity;
    }
}

方法2:HashMap + 手写DoubleList。

参考1、 LRU策略详解和实现

参考2、哈希表 + 双向链表

M.  涉及链表操作细节较多,很具有综合性,以后一定手写完成!!

原文地址:https://www.cnblogs.com/HuangYJ/p/14061336.html