LinkedHashMap使用

2025/04/09

一、背景

可以用LinkedHashMap去实现LRUCache,这里说一下它的用法。

二、原理

使用双向链表来维护遍历顺序。

三、应用场景

基于LRU算法的缓存。

四、实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @description 使用LinkedHashMap实现LRUCache
 * @date 2025-04-09
 */
public class LRUCache extends LinkedHashMap<Integer, Integer> {

    // 容量
    private int capacity;

    // 初始化
    public LRUCache(int capacity) {
        // 注意:accessOrder必须设置为true,才会有LRU的特性。否则,只会维护插入顺序
        super(capacity, 0.75f, true); // loadFactor是float类型的
        this.capacity = capacity;
    }

    // 根据key获取value。存在返回,不存在返回-1
    public int get(int key) {
        return super.getOrDefault(key, -1);
    }

    // 向缓存中插入(key, value)
    public void put(int key, int value) {
        super.put(key, value);
    }

    // 是否移除旧结点逻辑(双向链表的头部结点),触发条件。注意:此为实现固定大小的缓存的关键
    // it allows the map to reduce memory consumption(内存消耗) by deleting 
    // stale(不新鲜的) entries.
    @Override
    protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) {
        return super.size() > capacity;
    }
}

测试程序

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class LinkedHashMapTest {
    public static void main(String[] args) {
        // 初始化缓存,并且指定容量
        LRUCache lruCache = new LRUCache(3);
        // 插入结点
        lruCache.put(1, 1);
        // 插入结点
        lruCache.put(2, 2);
        // 插入结点
        lruCache.put(3, 3);
        System.out.println(lruCache.keySet());

        // 访问结点2
        int getRes01 = lruCache.get(2);
        System.out.println(lruCache.keySet());

        // 访问结点1
        int getRes02 = lruCache.get(1);
        System.out.println(lruCache.keySet());

        // 访问结点3
        int getRes03 = lruCache.get(3);
        System.out.println(lruCache.keySet());
    }
}

运行结果