集合源码学习(十一):LinkedHashMap

何为LinkedHashMap

LinkedHashMap是一个,具有顺序的HashMap,也就是使用Iterator进行迭代时,顺序与put进来的顺序是一致的。
先看LinkedHashMap的定义:

public class LinkedHashMap<K,V>
    extends HashMap<K,V>
    implements Map<K,V>

如上,LinkedHashMap继承自HashMap,并且里面基本的put,delete方法都是用的父类HashMap中的实现。也就是存储结构和父类一致。

所以本篇文章就不围绕LinkedHashMap的结构了,具体可以参照HashMap的:
集合源码学习(七):HashMap(Java8)

LinkedHashMap为什么是有序的?

首先看里面的Entry定义:

    /**
     * HashMap.Node subclass for normal LinkedHashMap entries.
     */
    static class Entry<K,V> extends HashMap.Node<K,V> {
        Entry<K,V> before, after;
        Entry(int hash, K key, V value, Node<K,V> next) {
            super(hash, key, value, next);
        }
    }

就是在每个节点上加了before和after引用,指向前后的引用。
在节点存储上也好理解,因为要有顺序嘛,所以会有前后两个引用。

回调方法

仔细的查看了下,LinkedHashMap里面竟然没有put等方法?
因为继承子HashMap嘛,父类实现了,自己就不用实现了~。
但是,如果自己没有实现put,那怎么把自己的before和after节点接上去呢?
回调方法
看HashMap源码时,
注意到它里面的put方法会调用afterNodeInsertion 方法,
remove方法,则会调用afterNodeRemoval 方法。
先看HashMap里面的这几个方法:

    // Callbacks to allow LinkedHashMap post-actions
    void afterNodeAccess(Node<K,V> p) { }
    void afterNodeInsertion(boolean evict) { }
    void afterNodeRemoval(Node<K,V> p) { }

jdk源码注释为,供LinkedHashMap回调使用。
什么意思呢?
我们再看LinkedHashMap里面,也有这三个方法:

    void afterNodeAccess(Node<K,V> e) { // move node to last
        LinkedHashMap.Entry<K,V> last;
        if (accessOrder && (last = tail) != e) {
            LinkedHashMap.Entry<K,V> p =
                (LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;
            p.after = null;
            if (b == null)
                head = a;
            else
                b.after = a;
            if (a != null)
                a.before = b;
            else
                last = b;
            if (last == null)
                head = p;
            else {
                p.before = last;
                last.after = p;
            }
            tail = p;
            ++modCount;
        }
    }



    void afterNodeInsertion(boolean evict) { // possibly remove eldest
        LinkedHashMap.Entry<K,V> first;
        if (evict && (first = head) != null && removeEldestEntry(first)) {
            K key = first.key;
            removeNode(hash(key), key, null, false, true);
        }
    }


   void afterNodeRemoval(Node<K,V> e) { // unlink
        LinkedHashMap.Entry<K,V> p =
            (LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;
        p.before = p.after = null;
        if (b == null)
            head = a;
        else
            b.after = a;
        if (a == null)
            tail = b;
        else
            a.before = b;
    }

在LinkedHashMap里面方法意思是,三种操作后把每个节点的before和after接起来。
那么又是怎么回调的呢?
Java多态技术
刚刚分析可知,HashMap里面这三个方法是没有具体实现的,而在LinkedHashmap里面有具体实现。
当HashMap进行put,delete,replace等操作时,调用的是自己的无任何意义的这三个方法。

而当LinkedHashMap进行put,delete,replace等操作时,调用的是自己进行对接before和after节点的方法。

这就是回调方法,LinkedHashMap里面实现就分析这么多,如果有不懂地方,欢迎在下面留言。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值