LinkedHashMap源码笔记(jdk8)

需先看HashMap源码:https://blog.csdn.net/yzh_1346983557/article/details/105456563

一、LinkedHashMap的成员变量

    //双向链表的头结点
    transient LinkedHashMap.Entry head;

    //双向链表的尾结点
    transient LinkedHashMap.Entry tail;

    //排序方式,true-访问顺序 false-插入顺序
    //默认是插入顺序存储:accessOrder = false;
    //accessOrder = true时表示访问顺序存储,就是最新访问的数据会放到链表尾部!(访问顺序的LinkedHashMap进行了get操作以后,重新排序,把get的Entry移动到双向链表的表尾。)
    final boolean accessOrder;

LinkedHashMap extends HashMap implements Map,可发现LinkedHashMap相比较HashMap多维护了2个成员变量head、tail,这2个变量就是LinkedHashMap实现双向链表的关键变量。

二、LinkedHashMap的静态内部类Entry

    static class Entry extends HashMap.Node {
        //新加成员变量before、after,用于双向链表的连接
        Entry before, after;
        Entry(int hash, K key, V value, Node next) {
            super(hash, key, value, next);
        }
    }

也是比HashMap.Node多维护了2个成员变量before、after,用于双向链表的连接。

三、LinkedHashMap的newNode()方法

    //HashMap.put()方法创建新Node会调用newNode()方法,LinkedHashMap重写了HashMap的newNode()
    Node newNode(int hash, K key, V value, Node e) {
        LinkedHashMap.Entry p =
                new LinkedHashMap.Entry(hash, key, value, e);
        //将新节点加入双向链表尾部
        linkNodeLast(p);
        return p;
    }

    //将新节点加入双向链表尾部
    // link at the end of list
    private void linkNodeLast(LinkedHashMap.Entry p) {
        LinkedHashMap.Entry last = tail;//记录旧尾节点
        tail = p;//将新节点作为尾节点
        if (last == null)
            head = p;//旧尾节点为空,新节点也作为头结点
        else {
            //否则,即双向链表中已添加过数据
            p.before = last;//旧尾节点作为新节点的before
            last.after = p;//新节点作为旧尾节点的after
        }
    }

HashMap.put()方法创建新Node会调用newNode()方法,LinkedHashMap重写了HashMap的newNode()。所以,往LinkedHashMap中put()数据时会调用linkNodeLast(),将新节点加入双向链表。

jdk1.7是在构造函数中调用init()方法,init()中直接new Entry()创建了一个空节点对象作为双向链表的初始节点。jdk1.8去除了这一操作,没有去new一个空节点作为链表初始节点,这样,链表中维护的节点就都是LinkedHashMap中实际存在的对象了。

四、LinkedHashMap.forEach()数据迭代方法

    public void forEach(BiConsumer action) {
        if (action == null)
            throw new NullPointerException();
        int mc = modCount;
        //从双向链表的head开始,依次after迭代。所以取数据和存数据顺序能相同。
        for (LinkedHashMap.Entry e = head; e != null; e = e.after)
            action.accept(e.key, e.value);
        if (modCount != mc)
            throw new ConcurrentModificationException();
    }

五、LinkedHashMap的数据结构图

图来源(侵权删):https://www.jianshu.com/p/8f4f58b4b8ab

LinkedHashMap源码笔记(jdk8)_第1张图片

实际上图是jdk1.7的LinkedHashMap的数据结构,jdk1.8中Entry header就是Entry1,偷懒拿来用一下。

 

 

你可能感兴趣的:(JDK,JAVA,java,LinkedHashMap)