使用LinkedHashMap实现LRU缓存
我试图使用LinkedHashMap实现LRU缓存。 在LinkedHashMap( http://docs.oracle.com/javase/7/docs/api/java/util/LinkedHashMap.html )的文档中,它说:
请注意,如果将键重新插入地图,则不会影响插入顺序。
但是当我做下面的提示
public class LRUCache extends LinkedHashMap { private int size; public static void main(String[] args) { LRUCache cache = LRUCache.newInstance(2); cache.put(1, 1); cache.put(2, 2); cache.put(1, 1); cache.put(3, 3); System.out.println(cache); } private LRUCache(int size) { super(size, 0.75f, true); this.size = size; } @Override protected boolean removeEldestEntry(Map.Entry eldest) { return size() > size; } public static LRUCache newInstance(int size) { return new LRUCache(size); } }
输出是
{1=1, 3=3}
这表明重新插入确实影响了订单。 有人知道任何解释吗?
正如Jeffrey指出的那样 ,您正在使用accessOrder。 创建LinkedHashMap时,第三个参数指定顺序的更改方式。
"true for access-order, false for insertion-order"
有关LRU的更详细实现,您可以查看http://www.programcreek.com/2013/03/leetcode-lru-cache-java/
但是您没有使用广告订单,而是使用了访问顺序 。
迭代次序是上次访问其条目的顺序,从最近访问到最近访问(访问顺序)
…
调用put或get方法会导致访问相应的条目
因此,当您修改缓存时,这是缓存的状态:
LRUCache cache = LRUCache.newInstance(2); cache.put(1, 1); // { 1=1 } cache.put(2, 2); // { 1=1, 2=2 } cache.put(1, 1); // { 2=2, 1=1 } cache.put(3, 3); // { 1=1, 3=3 }
这是我在AccessOrder中使用LinkedHashMap的实现。 它会将最新访问的元素移动到前面,这只会产生O(1)开销,因为底层元素被组织在一个双向链表中,同时也被哈希函数索引。 因此get / put / top_newest_one操作都需要花费O(1)。
class LRUCache extends LinkedHashMap{ private int maxSize; public LRUCache(int capacity) { super(capacity, 0.75f, true); this.maxSize = capacity; } //return -1 if miss public int get(int key) { Integer v = super.get(key); return v == null ? -1 : v; } public void put(int key, int value) { super.put(key, value); } @Override protected boolean removeEldestEntry(Map.Entry eldest) { return this.size() > maxSize; //must override it if used in a fixed cache } }
I also implement LRU cache with little change in code. I have tested and it works perfectly as concept of LRU cache. package com.first.misc; import java.util.LinkedHashMap; import java.util.Map; public class LRUCachDemo { public static void main(String aa[]){ LRUCache lruCache = new LRUCache<>(3); lruCache.cacheable("test", "test"); lruCache.cacheable("test1", "test1"); lruCache.cacheable("test2", "test2"); lruCache.cacheable("test3", "test3"); lruCache.cacheable("test4", "test4"); lruCache.cacheable("test", "test"); System.out.println(lruCache.toString()); } } class LRUCache{ private Map cache; private int windowSize; public LRUCache( final int windowSize) { this.windowSize = windowSize; this.cache = new LinkedHashMap(){ @Override protected boolean removeEldestEntry(Map.Entry eldest) { return size() > windowSize; } }; } // put data in cache public void cacheable(K key, T data){ // check key is exist of not if exist than remove and again add to make it recently used // remove element if window size is exhaust if(cache.containsKey(key)){ cache.remove(key); } cache.put(key,data); } // evict functioanlity @Override public String toString() { return "LRUCache{" + "cache=" + cache.toString() + ", windowSize=" + windowSize + '}'; } }