最近,我偶然发现了Java面试问题之一:
“使用Java集合类实现最近使用的列表(LRU)缓存吗?”
如果您以前曾处理过类似的问题,那么对您来说真的很容易。 否则,您将开始考虑实现LRU缓存的最佳收集类。 大多数人没有意识到LinkedHashMap
提供了支持,并且可以用最少的代码直接使用。
什么是最近最少使用(LRU)缓存
如果您知道此概念,请跳至实施部分。 缓存项逐出中使用了不同的算法。 最受欢迎的是最近最少使用的。 缓存始终具有有限的内存,并且只能包含有限数量的项目。 它使用一种算法来检测和驱逐不值得保留的物品。 研究表明,与旧项目相比,新项目最有可能很快获得访问。 LRU基于此观察。 该算法跟踪项目的上次访问时间。 逐出具有最旧访问时间戳的项目。
LRU缓存实施
如果您想实现LRU缓存, LinkedHashMap
确实很有帮助。 甚至Sun Java框架也使用此类来实现com.sun.tdk.signaturetest.util.LRUCache
和sun.security.ssl.X509KeyManagerImpl.SizedMap
。
对于实现,应该重写removeEldestEntry()
方法。 在put()
和putAll()
之后调用此方法。 Map根据其返回值删除旧条目。 如果此方法返回true
,那么将删除旧条目。 否则,它可以留在Map
。 此方法的默认实现返回false
。 在这种情况下,旧条目保留在Map中,永远不会被删除; 它只是充当一般的Map
集合类。 在大多数实现中,如果映射中的条目数大于初始容量,则此方法返回true
。
package code4reference.test;import java.util.LinkedHashMap;
import java.util.Map;public class LRUCacheImpl extends LinkedHashMap<Integer, String> {private static final long serialVersionUID = 1L;private int capacity;public LRUCacheImpl(int capacity, float loadFactor){super(capacity, loadFactor, true);this.capacity = capacity;}/*** removeEldestEntry() should be overridden by the user, otherwise it will not * remove the oldest object from the Map.*/@Overrideprotected boolean removeEldestEntry(Map.Entry<Integer, String> eldest){return size() > this.capacity;}public static void main(String arg[]){LRUCacheImpl lruCache = new LRUCacheImpl(4, 0.75f);lruCache.put(1, "Object1");lruCache.put(2, "Object2");lruCache.put(3, "Object3");lruCache.get(1);lruCache.put(4, "Object4");System.out.println(lruCache);lruCache.put(5, "Object5");lruCache.get(3);lruCache.put(6, "Object6");System.out.println(lruCache);lruCache.get(4);lruCache.put(7, "Object7");lruCache.put(8, "Object8");System.out.println(lruCache);}
}
println()
方法按过期状态打印对象。 从上面的代码中可以看到,在插入Object4之前就插入了Object1,Object2和Object3,并访问了object1,因此在输出的第一行中,在Object4之前打印了Object1。 插入Object5时,对象2从列表中逐出,因为该对象是列表中最旧的对象。 当访问object3时,它的提升将高于object5,并且当插入object6时,将驱逐对象1。 其余输出是不言自明的,希望您在理解输出时不会遇到困难。
{2=Object2, 3=Object3, 1=Object1, 4=Object4}
{4=Object4, 5=Object5, 3=Object3, 6=Object6}
{6=Object6, 4=Object4, 7=Object7, 8=Object8}
翻译自: https://www.javacodegeeks.com/2014/06/code4referencelist-recently-usedlru-implementation-using-linkedhashmap.html