在 Java 中实现 LRU(最近最少使用)缓存的一种常见方法是使用 LinkedHashMap
。LinkedHashMap
继承自 HashMap
并且具有可预测迭代顺序的特点。在其内部,它维护着一个双向链表来记录插入顺序或者访问顺序。
为了实现 LRU 缓存,我们可以利用 LinkedHashMap
的一个构造函数,它可以让你定义 accessOrder
布尔值。如果将 accessOrder
设置为 true
,那么在遍历时,访问顺序会被考虑,这正是我们实现 LRU 缓存机制所需要的。
我们可以通过继承 LinkedHashMap
并且重写其 removeEldestEntry
方法来定制何时移除最老的条目。这个方法会在每次添加新元素后调用,通过返回 true
或 false
来决定是否移除最老的元素。
下面是一个简单的 LRU 缓存实现的例子:
javaimport java.util.LinkedHashMap; import java.util.Map; public class LRUCache<K, V> extends LinkedHashMap<K, V> { private final int capacity; public LRUCache(int capacity) { super(capacity, 0.75f, true); // Initial capacity, load factor, and access order 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.get(1); // 访问元素1 cache.put(4, "D"); // 添加新元素,会移除2=B,因为它是最少被访问的 System.out.println(cache); // 输出 {3=C, 1=A, 4=D} } }
在这个例子中,我们创建了一个容量为3的 LRU 缓存。我们添加并访问元素,并观察当新元素被添加超出容量时,最少访问的元素(最老的元素)是否正确地被移除。
这种方法的优势在于它的简单性和直接利用 Java 标准库的功能,而不需要从头开始实现双向链表。但是,要注意的是,LinkedHashMap
的这种用法在多线程环境下可能不是线程安全的。如果需要在多线程环境中使用 LRU 缓存,可以考虑使用 Collections.synchronizedMap
包装 LRUCache
或者使用其他并发控制机制。