LinkedHashMap為什么是有序的(與put先后順序一致)


 本文版權歸 遠方的風lyh和博客園共有,歡迎轉載,但須保留此段聲明,並給出原文鏈接,謝謝合作,如有錯誤之處忘不吝批評指正!

 

絮叨絮叨

  首先呢,明白一點 LinkedHashMap是HashMap的子類,也就是說它就是一個HashMap(所以還是要對HashMap源碼有一定了解),至於它可以保證(有序)先后順序,只能說兒子比老子優秀!虎父無犬子,兒子在父親的基業上又有了獨到之處!原因呢?下面一起看看源碼((基於jdk1.8)就知曉了!(看源碼一定要有耐心,第一次看可能看不懂,后面再看可能還是看不懂,但是別放棄治療)。

    

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

源碼分析

 變量分析

   LinkedHashMap在HashMap基礎上擴展的這兩個成員變量要特別注意,這兩個變量是保證有序的基礎

    /**
     * The head (eldest) of the doubly linked list.
* 記錄第一個 key—value 對象關於
LinkedHashMap.Entry<K,V>的結構接下來就會分析
*/
   transient LinkedHashMap.Entry<K,V> head; /** * The tail (youngest) of the doubly linked list.
* 保存最后一個 key—value 對象
*/ transient LinkedHashMap.Entry<K,V> tail;

   

 LinkedHashMap.Entry<K,V>結構:

  它繼承了HashMap.Node<K,V>,  添加了兩個LinkedHashMap.Entry<K,V> 用來記錄它的前一個 和后一個put進入來的key-value對象(LinkedHashMap.Entry<K,V>),在在結構設計上保證了LinkedHashMap有序的可實現

   static class Entry<K,V> extends HashMap.Node<K,V> {
//它的前一個 和后一個put進入來的key-value對象 Entry
<K,V> before, after; Entry(int hash, K key, V value, Node<K,V> next) { super(hash, key, value, next); } }

   附上HashMap.Node<K,V>

static class Node<K,V> implements Map.Entry<K,V> {
        final int hash;
        final K key;
        V value;
        Node<K,V> next;

        Node(int hash, K key, V value, Node<K,V> next) {
            this.hash = hash;
            this.key = key;
            this.value = value;
            this.next = next;
        }
        //省略。。。。。。。
    }

 

 實現

     了解完結構我們再來看看它在代碼中是如何實現的,LinkedHashMap是HashMap的子類 ,在放入key-value時,它復用了HashMap的put方法

public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }


final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) { Node<K,V>[] tab; Node<K,V> p; int n, i; if ((tab = table) == null || (n = tab.length) == 0) n = (tab = resize()).length; if ((p = tab[i = (n - 1) & hash]) == null) //這里要格外注意 LinkedHashMap復寫了HashMap的 //newNode(hash, key, value, null) 方法 tab[i] = newNode(hash, key, value, null); //...... }
  LinkedHashMap復寫了HashMap的newNode(hash, key, value, null) 方法,代碼如下:
 1  Node<K,V> newNode(int hash, K key, V value, Node<K,V> e) {
 2         LinkedHashMap.Entry<K,V> p =
 3             new LinkedHashMap.Entry<K,V>(hash, key, value, e);
 4         linkNodeLast(p);
 5         return p;
 6     }
 7 /***有序的實現核心***/
 8 private void linkNodeLast(LinkedHashMap.Entry<K,V> p) {
 9     LinkedHashMap.Entry<K,V> last = tail;
10     tail = p;
11     if (last == null)
12         head = p;
13     else {
14         p.before = last;
15         last.after = p;
16     }
17 }

   舉一個場景來說明上面的有序核心實現方法,比如說有這么一個場景:  一個班有 1號小明同學 2號張三 3號小紅 4號李四同學,老師要知道學生進入教師的先后順序。老師在黑板上寫了 兩個詞  head,tail兩個字段 規定:

    1.第一個來的在 head來的在head、tail寫上自己的名字

    2.第二個及后續到的, 看到黑板上的tail字段后,找到這個同學(這個同學記住我之后到的 after) 通知自己到了(並記住在我之前的是這個同學before) 並修改tail字段為自己的名字

  例子:

    1.小明同學 第一個到  ,在黑板上 head,tail 都寫下 小明

    2.張三到了之后看到 tail是小明 記住 自己上一個(before)是小明 ,並修改tail為張三 ,通知小明,小明記下來自己的后面(afte)r是張三

    3小紅到了看到tail是張三 記住自己上一個(before)是張三 並修改tail為小紅,通知張三,張三記下來自己的后面(after)是小紅

    4李四到了。。。。。。。

  老師來了上課 看到head上寫的是小明  並詢問 小明 你后面是誰 , 小明回:小紅 再詢問 小紅 ....知道 詢問到李四 結束

  老師就知道了學生進入教室的順序 小明->張三->小紅->李四。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM