在理解了#7 介紹的HashMap後,咱們來學習LinkedHashMap的工做原理及實現。首先仍是相似的,咱們寫一個簡單的LinkedHashMap的程序:html
1node 2git 3github 4app 5函數 6post 7學習 8spa 93d 10 11 12 |
|
運行結果是:
1 2 3 4 5 6 7 8 |
|
咱們能夠觀察到,和HashMap的運行結果不一樣,LinkedHashMap的迭代輸出的結果保持了插入順序。是什麼樣的結構使得LinkedHashMap具備如此特性呢?咱們仍是同樣的看看LinkedHashMap的內部結構,對它有一個感性的認識:
沒錯,正如官方文檔所說:
Hash table and linked list implementation of the Map interface, with predictable iteration order. This implementation differs from HashMap in that it maintains a doubly-linked listrunning through all of its entries. This linked list defines the iteration ordering, which is normally the order in which keys were inserted into the map (insertion-order).
LinkedHashMap是Hash表和鏈表的實現,而且依靠着雙向鏈表保證了迭代順序是插入的順序。
在HashMap中提到了下面的定義:
1 2 3 4 |
|
LinkedHashMap繼承於HashMap,所以也從新實現了這3個函數,顧名思義這三個函數的做用分別是:節點訪問後、節點插入後、節點移除後作一些事情。
afterNodeAccess函數
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
就是說在進行put以後就算是對節點的訪問了,那麼這個時候就會更新鏈表,把最近訪問的放到最後,保證鏈表。
afterNodeInsertion函數
1 2 3 4 5 6 7 8 |
|
若是用戶定義了removeEldestEntry
的規則,那麼即可以執行相應的移除操做。
afterNodeRemoval函數
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
這個函數是在移除節點後調用的,就是將節點從雙向鏈表中刪除。
咱們從上面3個函數看出來,基本上都是爲了保證雙向鏈表中的節點次序或者雙向鏈表容量所作的一些額外的事情,目的就是保持雙向鏈表中節點的順序要從eldest到youngest。
put
函數在LinkedHashMap中未從新實現,只是實現了afterNodeAccess
和afterNodeInsertion
兩個回調函數。get
函數則從新實現並加入了afterNodeAccess
來保證訪問順序,下面是get
函數的具體實現:
1 2 3 4 5 6 7 8 |
|
值得注意的是,在accessOrder模式下,只要執行get或者put等操做的時候,就會產生structural modification
。官方文檔是這麼描述的:
A structural modification is any operation that adds or deletes one or more mappings or, in the case of access-ordered linked hash maps, affects iteration order. In insertion-ordered linked hash maps, merely changing the value associated with a key that is already contained in the map is not a structural modification. In access-ordered linked hash maps, merely querying the map with get is a structural modification.
不要犯了像ConcurrentModificationException with LinkedHashMap相似的問題。
總之,LinkedHashMap不愧是HashMap的兒子,和老子太像了,固然,青出於藍而勝於藍,LinkedHashMap的其餘的操做也基本上都是爲了維護好那個具備訪問順序的雙向鏈表