2016-05-10 57 views
2

我看着这个帖子:LinkedHashMap removeEldestEntry: How many elements are removed?LinkedHashMap removeEldestEntry是否删除2个元素?

它声明removeEldestEntry只删除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,3)覆盖(2,1)元素。在此之后,当我插入(4,1)时,我已经有2个元素,所以它应该删除最长的条目:(1,1)。但是,它同时删除了(2,3)(1,1),使我在地图中只有(4,1)

任何想法为什么?我认为这与被替换的关键字有关,并且(2,3)位于列表的开头,就像它是最年长的条目一样,尽管它不应该是。但我仍然困惑为什么它会删除2个元素。

在附注中,它看起来像是在LinkedHashMap的前面存储最年长的元素,这也会给我们一个固定的时间删除最老的条目。这是真的?

+0

不,它不会删除'1,1':https://ideone.com/WStVFc –

+0

嗯,你是对的,我的日食现在在调试器中显示相同的东西。以前我的eclipse可能有些bug。非常感谢您为我验证:)。 – Kevin

回答

2

LinkedHashMap的关键行为特征理解的是,地图的Map.Entry<Integer, Integer>成员组织维护插入顺序,回答你有关Map内成员的排序问题。因此,如果我们在您的main方法走过的每一行代码,我们会看到以下内容:

  1. c.set(2,1)后的LRUMap内容将是:{2=1}
  2. c.set(1,1)之后LRUMap的内容将为:{2=1, 1=1}
  3. c.set(2,3)之后LRUMap的内容将为:{2=3, 1=1}。此操作仅将密钥(2)的映射值从1更新为3,并且不是被认为是结构更改,因此会维护成员的顺序。
  4. c.set(4,1)之后LRUMap的内容将为:{1=1, 4=1}。映射:2=3被认为是最老的条目,因此将其删除(并保留映射:1=1)。

因为它是从你的意图明显,你想创建一个最近使用最少缓存,你应该考虑改变你的LinkedHashMap的建设,从插入顺序成员存储移开赞成最后访问会员排序。该LinkedHashMap类提供了一种替代的构造函数来支持这种类型的使用:如果您传递值

public LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) 

trueaccessOrder参数,成员映射将被存储在存取顺序(这是你想要用于LRU缓存),或者如果您传递值false作为参数accessOrder,成员映射将存储在插入订单中。