我看了这个线程:linkedhashmap removeeldestentry:删除了多少元素?
它指出removeldestentry只删除1个元素。这对我来说是有意义的,但是当我调试代码时,似乎删除了2个元素。我不知道为什么。
public class LRUCache {
LinkedHashMap<Integer, Integer> LRUMap;
public LRUCache(int capacity) {
LRUMap = new LinkedHashMap<Integer, Integer>() {
@Override
protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) {
return LRUMap.size() > capacity;
}
};
}
public int get(int key) {
if (LRUMap.containsKey(key)) {
int val = LRUMap.remove(key);
LRUMap.put(key, val);
return val;
}
return -1;
}
public void set(int key, int value) {
LRUMap.put(key, value);
}
public static void main(String[] args) {
LRUCache c = new LRUCache(2);
c.set(2,1);
c.set(1,1);
c.set(2,3);
c.set(4,1);
}
}
因此,您可以从中看到,它将插入: (2,1)
以及 (1,1)
. 下一个因素是事情变得一团糟。因为键2已经存在,它会覆盖 (2,1)
具有的元素 (2,3)
. 在此之后,当我插入 (4,1)
,我已经有2个元素,所以应该删除最老的条目: (1,1)
. 但是,它同时删除了这两个 (2,3)
以及 (1,1)
只留给我 (4,1)
在Map上。
知道为什么吗?我想这和钥匙被换掉和 (2,3)
在列表的开头,好像它是最老的条目,尽管它不应该是。但我仍然不明白为什么它会删除2个元素。
另一方面,它看起来像是将最老的元素存储在 LinkedHashMap
,这也会给我们一个固定的时间删除最老的条目。这是真的吗?
1条答案
按热度按时间0yycz8jy1#
人的主要行为特征
LinkedHashMap
要明白的是Map.Entry<Integer, Integer>
对Map的成员进行组织以保持插入顺序,这将回答与Map中成员顺序相关的问题Map
. 所以如果我们在你的main
方法,我们将看到以下内容:之后
c.set(2,1)
内容LRUMap
将:{2=1}
.之后
c.set(1,1)
内容LRUMap
将:{2=1, 1=1}
.之后
c.set(2,3)
内容LRUMap
将:{2=3, 1=1}
. 此操作只是更新为键Map的值(2
)从1
至3
并且不被认为是结构上的变化,所以保持了构件的顺序。之后
c.set(4,1)
内容LRUMap
将:{1=1, 4=1}
. Map:2=3
被认为是最老的条目,因此它被删除(Map:1=1
保留)。因为从您的意图可以清楚地看出,您希望创建一个最近最少使用的缓存,所以您应该考虑更改缓存的结构
LinkedHashMap
从插入顺序成员存储转移到最后访问成员顺序。这个LinkedHashMap
类提供了一个替代构造函数来支持此类型的用法:如果传递值:
true
对于accessOrder
参数时,成员Map将按访问顺序存储(这是您要用于lru缓存的顺序),或者如果您传递以下值:false
对于accessOrder
参数时,成员Map将按插入顺序存储。