LinkedHashMap源码笔记(jdk8)

14 篇文章 1 订阅

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

一、LinkedHashMap的成员变量

    //双向链表的头结点
    transient LinkedHashMap.Entry<K,V> head;

    //双向链表的尾结点
    transient LinkedHashMap.Entry<K,V> tail;

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

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

二、LinkedHashMap的静态内部类Entry

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

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

三、LinkedHashMap的newNode()方法

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

    //将新节点加入双向链表尾部
    // link at the end of list
    private void linkNodeLast(LinkedHashMap.Entry<K,V> p) {
        LinkedHashMap.Entry<K,V> 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<? super K, ? super V> action) {
        if (action == null)
            throw new NullPointerException();
        int mc = modCount;
        //从双向链表的head开始,依次after迭代。所以取数据和存数据顺序能相同。
        for (LinkedHashMap.Entry<K,V> 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

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

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值