Java LinkedHashMap 实现 LRU

  1. LinkedHashMap 有两种使用模式:insert-order 和 access-order。通过指定构造方法accessOrder参数来决定使用哪种模式
    /**
     * Constructs an empty <tt>LinkedHashMap</tt> instance with the
     * specified initial capacity, load factor and ordering mode.
     *
     * @param  initialCapacity the initial capacity
     * @param  loadFactor      the load factor
     * @param  accessOrder     the ordering mode - <tt>true</tt> for
     *         access-order, <tt>false</tt> for insertion-order
     * @throws IllegalArgumentException if the initial capacity is negative
     *         or the load factor is nonpositive
     */
    public LinkedHashMap(int initialCapacity,
                         float loadFactor,
                         boolean accessOrder) {
        super(initialCapacity, loadFactor);
        this.accessOrder = accessOrder;
    }
  1. insert-order 在迭代 LinkedHashMap 时,会按插入的顺序依次访问 key value。
  2. access-order 则表示将 LinkedHashMap 作为 LRU 缓存来使用,也即:
  • get(key) 访问缓存中的元素时,需要记录下来,表明此 key 是最近被访问过的,作为后面淘汰 key 的依据。
  • 在淘汰缓存中的元素时,最久未被访问的 key 需要被删除。这通过:继承 removeEldestEntry 方法来实现

实现 LRUCache 类:

  1. LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存。缓存需要一个容量,当缓存中的元素超过此容量时,执行汰换。
  2. 可用过 size() 方法获取缓存当前的元素个数。java.util.HashMap#size
  3. int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
  4. void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。
import java.util.*;
class LRUCache<K,V> extends LinkedHashMap<Integer, Integer>{
    private int capacity;//缓存需要一个容量,当缓存中的元素超过此容量时,执行汰换。
    public LRUCache(int capacity) {
        //true 表示 创建 LinkedHashMap 时, 采用: access-order(false 时为:insertion-order)
        super(capacity,0.75f,true);
        this.capacity = capacity;
    }
    
    public int get(int key) {
        //如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1
       Integer value =  super.getOrDefault(key, -1);
       return value;
    }
    
    public void put(int key, int value) {
        super.put(key, value);
    }

    @Override
    protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) {
        //缓存中的元素大于 capacity 时,执行汰换。在 put 操作时,会自动调用此方法,删除最久未被访问的key
        return size() > capacity ;
    }
}

LinkedHashMap

public class Test {
    public static void main(String[] args) {
        //access order 为 true,可以用作lru,创建 LinkedHashMap 时,access order 默认为 false,也即采用的是 insert order,元素插入的顺序
        LinkedHashMap<String, Integer> lru = new LinkedHashMap<>(20, 0.75f, false);

        LinkedHashMap<String, Integer> insertMap = new LinkedHashMap<>();
//        LinkedHashMap<String, Integer> insertMap = new LinkedHashMap<>(20, 0.75f, true);
        insertMap.put("c", 3);
        insertMap.put("a", 1);
        insertMap.put("b", 2);

        for (Map.Entry<String, Integer> entry : insertMap.entrySet()) {
            //key=c value=3
            //key=a value=1
            //key=b value=2
            System.out.println("key=" + entry.getKey() + " value=" + entry.getValue());
        }
    }
}

原题参考:https://leetcode.cn/problems/lru-cache/description/

使用java.util.LinkedList模拟实现内存页面置换算法--LRU算法

posted @ 2023-07-24 00:35  大熊猫同学  阅读(30)  评论(0编辑  收藏  举报