【问题标题】:LinkedHashMap Structure for LRU CacheLRU 缓存的 LinkedHashMap 结构
【发布时间】:2012-08-15 08:16:51
【问题描述】:

我对如何使用 LinkedHashMap (How would you implement an LRU cache in Java 6?) 构建 LRU 缓存有点困惑,我想确保我了解它在幕后内部是如何工作的。

假设我定义了一个类 LRUMap,它扩展了 LinkedHashMap 并覆盖了removeEldestEntry(final Map.Entry<A, B> eldest),就像它的方式一样。

然后我构造数据结构并将4个项目插入到地图中

    LRUMap<String,String> map = new LRUMap<String,String>(3); //capacity 3
    map.put("a", "a");
    map.put("b", "b");
    map.put("c", "c");
    map.put("d", "d");

另外LinkedHashMap 使用名为headerEntry object 作为起始节点来链接您添加到地图的所有项目。所以在这种情况下,它将是

   [header] ->  ["a"] -> ["b"] -> ["c"] -> ["d"] -> [header]

headerEntry对象是双向链表的开始和结束,因为header.before=header.after=header在最初构造时。

假设地图达到了我想要的最大条目(3 个项目),并且来自

    Entry<K,V> eldest = header.after;
    if (removeEldestEntry(eldest)) {
         removeEntryForKey(eldest.key);
    }
    .....

这是否意味着它将首先删除 ["a"] ?
当我们调用get(Object key) 时,它是否会重新排列列表顺序,将键(比如说“b”)放在标题节点之前,所以它变成了

     [header] ->  ["c"] -> ["d"] -> ["b"] -> [header]

只是想澄清一下。

【问题讨论】:

    标签: java linkedhashmap


    【解决方案1】:
    1. 是的;条目&lt;"a", "a"&gt; 将首先被删除:-)
    2. 也许; LinkedHashMap 默认使用 insertion-order,而不是 access-order... 直接来自the specification

      Map 接口的哈希表和链表实现,具有可预测的迭代顺序。这个实现与HashMap 的不同之处在于它维护了一个双向链表,贯穿其所有条目。这个链表定义了迭代顺序,通常是键插入映射的顺序(insertion-order)。

      话虽如此,LinkedHashMap 也支持 access-order;

      提供了一个特殊的constructor 来创建链接哈希映射,其迭代顺序是其条目最后一次访问的顺序,从最近最少访问到最近访问(访问顺序)。这种映射非常适合构建 LRU 缓存。调用putget 方法会导致访问相应的条目(假设它在调用完成后存在)。

      所以,如果您使用 insertion-order,那么顺序不会从 get("b") 更改;如果您使用 access-order(通常是 LRU 缓存 ;-),那么顺序 改变。

    还有其他问题吗? :-)

    【讨论】:

    • @user1389813 因为您在这里显得较新,请不要忘记标记答案accepted,这对解决问题有很大帮助。
    • 只是想知道我们可以对 LFU 缓存使用相同的策略吗?或您喜欢的任何其他数据结构?
    • @user1389813 不,使用LinkedHashMap 实现LFU 缓存可能没有一种简单的通用方法:-/ 话虽如此,一般来说,最不常用的元素具有天生的倾向最近最少使用的一个。
    猜你喜欢
    • 2015-02-13
    • 1970-01-01
    • 2011-05-25
    • 1970-01-01
    • 1970-01-01
    • 2018-11-02
    • 2011-03-02
    • 1970-01-01
    • 2011-01-31
    相关资源
    最近更新 更多