中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何深入解讀LinkedHashMap原理和源碼

發布時間:2021-12-03 18:37:57 來源:億速云 閱讀:159 作者:柒染 欄目:云計算

如何深入解讀LinkedHashMap原理和源碼,相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。

LinkedHashMap 顧名思義,就是一個基于 HashMap 的雙向鏈表的集合。其中 HashMap 為數組加單向鏈表的結構,LinkedList 為雙向鏈表實現的。而 LinkedHashMap 正是二者的結合體。

如何深入解讀LinkedHashMap原理和源碼  

首先,從源碼上來看,LinkedHashMap 繼承自 HashMap,所以 HashMap 有的大部分特性,LinkedHashMap 都有。比如:線程安全問題等。關于 HashMap 推薦閱讀《搞不懂 HashMap?只因你缺一個 HashMap 的原理機制流程圖!》。 

如何深入解讀LinkedHashMap原理和源碼  

順著 LinkedHashMap 的源碼往下看,你會發現 LinkedHashMap 提供了 5 個構造函數。基本上就是對 HashMap 的構造函數做了擴展,加了一個重要的參數 accessOrder,它代表的是一個訪問順序,后面會具體的講。

如何深入解讀LinkedHashMap原理和源碼  

注意上圖,LinkedHashMap 還有一個改變就是多了兩個屬性:header 和 accessOrder。header 就是雙向鏈表的表頭元素。當 accessOrder 為 true 時,代表按訪問順序迭代,false 時表示按照插入順序。這個配圖來自網上,是基于 JDK1.6 的,現在 JDK8 的變化已經很大了。

LinkedHashMap 繼承了 HashMap 中大部分的方法,只是多了雙向鏈表。

如何深入解讀LinkedHashMap原理和源碼  

LinkedHashMap 的 Entry 增加了用于維護順序的 before 和 after 變量,就是用來確定鏈表的前后節點。本來無序的數組 + 鏈表結構,通過 before 和 after 把它們關聯起來,變的有序。在 put 和 get 的時候維護好了這個雙向鏈表,遍歷的時候就有序了。

LinkedHashMap 的節點 Entry 繼承自 HashMap.Node,然后將單向鏈表改成了一個雙向鏈表。

如何深入解讀LinkedHashMap原理和源碼  

LinkedHashMap 并沒有重寫任何 put 方法。但是其重寫了構建新節點的 newNode() 方法。
newNode() 會在 HashMap 的 putVal() 方法里被調用,putVal() 方法會在批量插入數據 putMapEntries(Map m, boolean evict) 或者插入單個數據 public V put(K key, V value) 時被調用。

LinkedHashMap 重寫了 newNode(),在每次構建新節點時,通過 linkNodeLast(p); 將新節點鏈接在內部雙向鏈表的尾部。

如何深入解讀LinkedHashMap原理和源碼  

其中的 linkNodeLast 方法,會將新增的節點。如果,集合之前是空的,指定 head 節點;否則將新節點連接在鏈表的尾部。

另外 LinkedHashMap 的 afterNodeInsertion 方法也非常的重要,它會在新節點插入之后回調,根據 evict 和 first 判斷是否需要刪除最老插入的節點。

如何深入解讀LinkedHashMap原理和源碼  

LinkedHashMap 還重寫了 afterNodeRemoval 這個方法。在刪除節點 e 時,同步將 e 從雙向鏈表上刪除。

如何深入解讀LinkedHashMap原理和源碼  

另外 get() 和 getOrDefault() 方法也被重寫了。因為我們要根據 accessOrder 規則來調整具體的獲取方法。在 accessOrder 為 true 的情況下,要去回調 void afterNodeAccess(Node e) 函數。

如何深入解讀LinkedHashMap原理和源碼  

在 afterNodeAccess() 函數中,會將當前被訪問到的節點 e,移動至內部的雙向鏈表的尾部。

如何深入解讀LinkedHashMap原理和源碼  

通過上圖的解釋,你會發現。afterNodeAccess 方法埋下了隱患,會修改 modCount,因此當你正在 accessOrder=true 的模式下,迭代 LinkedHashMap 時,如果同時查詢訪問數據,也會導致 fail-fast,因為迭代的順序已經改變。

最后,總結一下。LinkedHashMap 相對于 HashMap 的源碼比,是很簡單的。因為大樹底下好乘涼。它繼承了 HashMap,僅重寫了幾個方法,以改變它迭代遍歷時的順序。這也是其與 HashMap 相比最大的不同。在每次插入數據,或者訪問、修改數據時,會增加節點、或調整鏈表的節點順序。以決定迭代時輸出的順序。

  • accessOrder,默認是 false,則迭代時輸出的順序是插入節點的順序。

    若為 true,則輸出的順序是按照訪問節點的順序。

    為 true 時,可以在這基礎之上構建一個 LruCache。

    參考《手把手教你用LinkedHashMap打造FIFO和LRU緩存系統》

  • LinkedHashMap 并沒有重寫任何 put 方法。

    但是其重寫了構建新節點的 newNode() 方法.在每次構建新節點時,將新節點鏈接在內部雙向鏈表的尾部

  • accessOrder=true 的模式下,在 afterNodeAccess() 函數中,會將當前被訪問到的節點 e,移動至內部的雙向鏈表的尾部。

    值得注意的是,afterNodeAccess() 函數中,會修改 modCount,因此當你正在 accessOrder=true 的模式下,迭代 LinkedHashMap 時,如果同時查詢訪問數據,也會導致 fail-fast,因為迭代的順序已經改變。


  • nextNode() 就是迭代器里的next()方法。

    該方法的實現可以看出,迭代 LinkedHashMap,就是從內部維護的雙鏈表的表頭開始循環輸出。

    而雙鏈表節點的順序在LinkedHashMap的增、刪、改、查時都會更新。

    以滿足按照插入順序輸出,還是訪問順序輸出。


  • 它與 HashMap 比,還有一個小小的優化,重寫了 containsValue() 方法,直接遍歷內部鏈表去比對 value 值是否相等。

看完上述內容,你們掌握如何深入解讀LinkedHashMap原理和源碼的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

拉孜县| 民丰县| 宁乡县| 通山县| 古丈县| 六安市| 闻喜县| 皮山县| 罗山县| 马公市| 衡山县| 逊克县| 钟山县| 交口县| 商水县| 台湾省| 长春市| 蓬溪县| 黄骅市| 兴仁县| 和林格尔县| 天门市| 乌鲁木齐县| 潢川县| 文昌市| 岳阳县| 茂名市| 郴州市| 宿松县| 厦门市| 兴安盟| 绥芬河市| 洛阳市| 奉化市| 乌拉特前旗| 南靖县| 育儿| 普宁市| 大庆市| 习水县| 建平县|