若是你用過HashMap那麼確定知道HashMap是不能保證有序性的,之因此HashMap不能保證有序性是由於存放數組位置的數據時根據hash函數決定的;可是有沒有可以保證有序性的Map呢?那就是LinkedHashMap,下面咱們經過代碼來看一下HashMap的無序和LinkedHashMap的有序性。數組
HashMap無序微信
![](http://static.javashuo.com/static/loading.gif)
LinkedHashMap有序app
LinkedHashMap一共有5個構造方法,其中有4個的構造方法都是指定了accessOrder爲false,只有第一個能夠自定義accessOrder的狀態,accessOrder實際上就是指定排序的規則;若是accessOrder爲false表示根據插入的順序進行排序,當爲true的時候表示根據獲取排序。可看以下實例代碼less
插入順序爲45,55,53而後獲取了55,45排序順序變爲53,44,45。編輯器
一樣在看源碼以前咱們先看一下LinkedHashMap的繼承與實現關係圖。能夠看到LinkedHashMap繼承HashMap,同時實現了Map接口。函數
LinkedHashMap對HashMap的newNode、afterNodeAccess、afterNodeInsertion方法進行都進行了重寫,同時也對HashMap中的Node進行了重寫增長了before和after字段。spa
回到LinkedHashMap的put方法。當咱們debug進入到LinkedHashMap後實際上就是調用了HashMap的put方法。.net
在putVal中先判斷Node是否須要爲空,爲空進行初始化,若是不爲判斷對應數組下標中是否有值,若是沒有調用newNode方法。在newNode中調用linkNodeLast。debug
linkNodeLast拿到尾部節點。若是尾部爲空直接把第一個當前節點設置爲頭和尾節點,若是不爲空則拿到尾部節點同時將當前節點的before設置爲尾部節點即前一個節點,而將前一個節點的after設置爲當前節點。這個before和after是否是就是一個雙向鏈表的意思。3d
在HashMap中實際上並無對afterNodeInsertion方法進行任何實現,而在LinkedHashMap中作了具體的實現操做。可是在JDK8中不會執行,由於removeEldestEntry方法始終返回false。
實際上LinkedList可以實現有序就是由於重寫了Node並增長了before和after字段,同時對newNode方法進行了重寫,有序就是由於before和after字段
LinkedHashMap的get方法與HashMap中get方法的不一樣點也在於多了afterNodeAccess()方法。afterNodeAccess方法在執行時必須accessOrder爲true,也就是必須是根據獲取排序時纔會執行。
詳細看一下afterNodeAccess是怎麼實現的,afterNodeAccess實際上就是把當前獲取的節點的after和before進行從新變化,也就是移動到最後面去。
reomve方法也直接使用了HashMap中的remove,LinkedHashMap重寫了其中的afterNodeRemoval該方法在HashMap中沒有具體實現,經過此方法在刪除節點的時候調整了雙鏈表的結構。
LinkedHashMap之因此能保證有序性是由於在HashMap的Node基礎上又增長了after和before字段,至關有又是一個雙向鏈表來維護有序性。結構以下
本文分享自微信公衆號 - 大貓的Java筆記(damaoJava)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。