我试图使用LinkedHashMap实现LRU缓存。 在LinkedHashMap(http://docs.oracle.com/javase/7/docs/api/java/util/LinkedHashMap.html)的文档中,它说:
请注意,如果将某个键重新插入地图,插入顺序不会受到影响。
但是,当我执行以下操作时
public class LRUCache<K, V> extends LinkedHashMap<K, V> {
private int size;
public static void main(String[] args) {
LRUCache<Integer, Integer> 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<K, V> eldest) {
return size() > size;
}
public static <K, V> LRUCache<K, V> newInstance(int size) {
return new LRUCache<K, V>(size);
}
}
输出
{1=1, 3=3}
这表示重新插入确实影响了订单。 有人知道任何解释吗?
答案 0 :(得分:19)
As pointed out by Jeffrey,您正在使用accessOrder。创建LinkedHashMap时,第三个参数指定顺序的更改方式。
"true for access-order, false for insertion-order"
有关LRU的更详细实现,您可以查看此内容 http://www.programcreek.com/2013/03/leetcode-lru-cache-java/
答案 1 :(得分:5)
但您没有使用广告订单,而是使用access order。
迭代顺序是其条目的最后顺序 访问,从最近访问到最近(访问顺序)
...
调用put或get方法会导致访问 相应的条目
因此,当您修改缓存时,这是缓存的状态:
LRUCache<Integer, Integer> 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 }
答案 2 :(得分:3)
这是我在AccessOrder中使用LinkedHashMap的实现。它会将最新访问的元素移动到前面,这只会产生O(1)开销,因为底层元素组织在一个双向链表中,同时也被哈希函数索引。因此get / put / top_newest_one操作都需要花费O(1)。
class LRUCache extends LinkedHashMap<Integer, Integer>{
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<Integer, Integer> eldest) {
return this.size() > maxSize; //must override it if used in a fixed cache
}
}
答案 3 :(得分:0)
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<String, String> 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<K, T>{
private Map<K,T> cache;
private int windowSize;
public LRUCache( final int windowSize) {
this.windowSize = windowSize;
this.cache = new LinkedHashMap<K, T>(){
@Override
protected boolean removeEldestEntry(Map.Entry<K, T> 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 +
'}';
}
}
答案 4 :(得分:0)
我使用了以下代码及其工作!!!! 我已将窗口大小设为4,但可以采用任何值。
用于广告订单:
1:检查密钥是否存在。
2:如果是,则将其删除(通过使用lhm.remove(key))
3:添加新的键值对。
用于访问顺序:
无需删除键,只需put和get语句即可自动完成所有操作。
此代码用于访问订单:
import java.util.LinkedHashMap;
public class LRUCacheDemo {
public static void main(String args[]){
LinkedHashMap<String,String> lhm = new LinkedHashMap<String,String>(4,0.75f,true) {
@Override
protected boolean removeEldestEntry(Map.Entry<String,String> eldest) {
return size() > 4;
}
};
lhm.put("test", "test");
lhm.put("test1", "test1");
lhm.put("1", "abc");
lhm.put("test2", "test2");
lhm.put("1", "abc");
lhm.put("test3", "test3");
lhm.put("test4", "test4");
lhm.put("test3", "test3");
lhm.put("1", "abc");
lhm.put("test1", "test1");
System.out.println(lhm);
}
}
答案 5 :(得分:0)
技术上 LinkedHashMap 具有以下构造函数。这有助于我们使访问顺序为真/假。如果为假,则保持插入顺序。
LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder)
(#Constructs an empty LinkedHashMap instance with the specified initial capacity, load factor and ordering mode)
以下是LRU Cache的简单实现---
class LRUCache {
private LinkedHashMap<Integer, Integer> linkHashMap;
public LRUCache(int capacity) {
linkHashMap = new LinkedHashMap<Integer, Integer>(capacity, 0.75F, true) {
@Override
protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) {
return size() > capacity;
}
};
}
public void put(int key, int value) {
linkHashMap.put(key, value);
}
public int get(int key) {
return linkHashMap.getOrDefault(key, -1);
}
}