【问题标题】:How does LinkedHashMap work under the hood?LinkedHashMap 如何在幕后工作?
【发布时间】:2012-06-07 21:03:55
【问题描述】:

我读到了关于LinkedHashMap 的信息,并且从描述中(虽然很有趣)我无法理解它实际上是如何在幕后工作的。作为旁注,我知道 HashMap 在 Java 中是如何工作的。
所以我查看了源代码,但仍然无法弄清楚它是如何工作的。在这种情况下,也许我没有掌握 OOP 中的一些基本知识,所以请耐心等待。
总结一下让我感到困惑的部分如下:
LinkedHashMap 将所有调用委托给其父 HashMap
在内部,它覆盖 HashMap.Entry 以实现各种 recordAccessrecordRemoval 方法,这些方法似乎实现了 LinkedHashMap 的逻辑
但实际的Entries 位于基类的表中,即HashMap,它实例化了HashMap.Entry 而不是LinkedHashMap.Entry 的表。
所以我无法弄清楚各种recordAccessrecordRemove 等实际上是如何被调用的。
那么任何人都可以帮助我了解这里发生了什么吗?
我是否正确地认为LinkedHashedMap.EntryHashMap 创建的表类型?但是怎么做?

更新:
我的问题是如何调用recordAccess。我使用派生版本的HashMap 对此进行的实验失败了,原因是Shengyuan Lu (+1) - 我错了

更新:
我尝试的以下内容与LinkedHashMap 所做的相同(我认为):

package delete;  

public class Base<T> {  

    Entry<T>[] table;  
    int idx = 0;  
    @SuppressWarnings("unchecked")  
    public Base(){  
        System.out.println("In base");  
        table = new Entry[10];  
    }

    public void add(T x){  
        table[idx] = new Entry(x);  
        table[idx].doSomething();  
    }  

    static class Entry<T>{  
        T value;  

        Entry(T x){  
            this.value = x;  
            System.out.println("Entry::Base");  
        }

        void doSomething(){  
            System.out.println("In Entry base, doing something");  
        }  
    }  

}  




public class Derived<T> extends Base<T> {  

    static class Entry<T> extends Base.Entry<T>{  

        Entry(T x) {  
            super(x);  
            System.out.println("In Entry derived");  
        }  

        int val;  

        @Override  
        void doSomething() {  
            System.out.println("In Entry derived doing something really smart!");  
        }       
    }  

    /**
     * @param args
     */
    public static void main(String[] args) {  

        Base<String> b = new Derived<String>();  
        b.add("Test string");  

    }  

}  

但它会打印:

In base  
Entry::Base     
In Entry base, doing something    

所以派生的Entry 永远不会被调用。
我的例子有什么不同吗?我不明白这对LinkedHashMap 是如何工作的

【问题讨论】:

  • 受保护还是包私有?
  • forLinkedHashMap为什么定义为extendsHashMap实现Map阅读this
  • @Pshemo:谢谢。在解释了您的链接后,我更新了 OP。现在我需要的只是解决我的核心问题

标签: java oop dictionary collections hashmap


【解决方案1】:

如果你在包java.util下定义MyLinkedHashMap,它会编译;)

因为HashMap.HashEntry 是包的可见性。

加:

我认为让您感到困惑的主要事情是 LinkedHashMap.EntryHashMap.Entry。重点是LinkedHashMap.Entry is-a HashMap.Entry。实际上 HashMap.table 将 LinkedHashMap.Entry 存储在 LinkedHashMap 中。

关于recordAccessrecordRemoval,它们都覆盖了HashMap.Entry 版本。您可以在 LinkedHashMap 和 HashMap 中找到参考。

在此处合并 cmets:您的示例代码与 LinkedHashMap 实现不同。请参阅LinkedHashMap.addEntry()

【讨论】:

  • 但是怎么做?HashMap table = new Entry[DEFAULT_INITIAL_CAPACITY];
  • @user384706 想想Object[] table=new Object[1]; table[0] = "I am subclass of Object";
【解决方案2】:

Ctrl+F 在这里是您的朋友,尤其是当它允许您一次搜索多个文件时。 recordAccess 由映射的putget 方法在访问/创建的条目上调用。 (调用在HashMap.putHashMap.putForNullKeyLinkedHashMap.get 中。)只有在使用带有布尔参数并将true 传递给它的LinkedHashMap 的构造函数时才有意义。这样做的效果是,每当你触摸地图时,被触摸的条目都会被移动到内部链表的前面。

引用文档:

提供了一个特殊的构造函数来创建链接哈希映射,其迭代顺序是其条目最后一次访问的顺序,从最近最少访问到最近访问(访问顺序)。这种映射非常适合构建 LRU 缓存。调用 put 或 get 方法会导致访问相应的条目(假设它在调用完成后存在)。 putAll 方法为指定映射中的每个映射生成一个条目访问,按照指定映射的条目集迭代器提供键值映射的顺序。没有其他方法生成条目访问。特别是,collection-views 上的操作不会影响 backing map 的迭代顺序。

removeEldestEntry(Map.Entry) 方法可能会被覆盖,以便在向地图添加新映射时自动删除陈旧的映射。

类似地,recordRemovalHashMap.removeEntryForKeyHashMap.removeMapping 调用。

【讨论】:

    猜你喜欢
    • 2014-11-18
    • 2011-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多