LinkedHashMap原始碼分析

2021-09-24 22:16:49 字數 2377 閱讀 7255

linkedhashmap是hashmap的子類,和hashmap不同的是它內部還使用了乙個雙向鍊錶將所有元素連線在了一起,然後基於這個雙向鍊錶實現了fifo和lru兩種元素訪問策略。本文的目的是連線linkedhashmap內部的實現機制,然後基於它實現乙個簡單的lru。

linkedhashmap中每個元素的資料結構如下:

可以看出它是對hashmap的node結構進行了拓展

linkedhashmap中元素的遍歷:

所以內部其實就是鍊錶的遍歷,這個實現就要比hashmap簡單多的,hashmap是按照table的順序進行遍歷。既然是按照鍊錶遍歷的,那麼它的fifo和lru訪問策略是如何實現的呢?

(ps: linkedhashmap的fifo & lru訪問策略說明:

linkedhashmap內部使用accessorder屬性來控制使用哪種策略,預設為false,即fifo,鍊錶中的順序就是元素插入時的順序,遍歷是是按照元素插入的順序訪問的。設定為true時就是lru

策略。此時會調整鍊錶中元素的順序,會把訪問的節點放入鍊錶的末尾(tail位置,訪問時都是從head開始),每次刪除head指向的元素就可以達到lru的效果。

由於linkedhashmap是hashmap的子類,很多方法都是使用父類hashmap中的方法,所以此處就不再另行解釋了,有興趣的可以看下我之前寫的分析hashmap的那篇文章,本文只分析幾個linkedhashmap有過改動或者特有的幾個方法。

)put()插入資料(lru模式下會刪除超過容量的元素):

呼叫的是hashmap中的put(),不同的是重寫了其中的newnode()方法,完成了鍊錶的構建,將元素新增到鍊錶的尾部。

lru模式下,會刪除超過容量的元素,從head開始刪除:

removenode()方法內部會呼叫hashmap中的remove()方法刪除map中的元素,接著還會呼叫afternoderemoval(node)

可以看出來,remove()方法會刪除map中的資料,但是鍊錶中元素的順序不會做調整。

get()獲取元素(lru模式下還會調整鍊錶中元素的順序):

afternodeaccess()本質上就是將元素從當前位置移到鍊錶末尾:

(ps: 從++modcount可以看出,linkedhashmap是非執行緒安全的)

基於linkedhashmap實現乙個簡單的lrumap:

public class lrumapextends linkedhashmap

protected void add(k value)

@override

protected boolean removeeldestentry(map.entryeldest)

}

//測試**

lrumapcache = new lrumap<>(3);

cache.add("a");

cache.add("b");

cache.add("c");

cache.add("d");

cache.get("c");

cache.foreach((k, v) -> system.out.println(k));

//輸出為:b d c

其實這個**繼承linkedhashset會更加簡單一點

參考:

AbstractCollection原始碼分析

abstractcollection抽象類提供了collection的骨架實現,collection分析請看 這裡直接看它的 是如何實現的.public abstract iterator iterator 該方法沒有實現.public abstract int size 該方法沒有實現.publi...

ThreadPoolExecutor原始碼閱讀

執行緒池解決兩個問題 一是復用執行緒,減少建立銷毀執行緒帶來系統開銷 二是限定系統資源使用邊界,避免大量執行緒消耗盡系統記憶體 適用於互不依賴,執行時間短,不需要對執行緒控制操作的執行緒 新增任務時,1.若執行緒數量小於corepoolsize,則新增執行緒執行任務 2.若執行緒數量大於等於core...

OrangePi One Android 原始碼編譯

一 系統環境搭建參照 二 lichee原始碼編譯 1.檢視help build.sh h2.配置核心 cd linux 3.4 make arch arm menuconfig 進入配置頁面,上下移動列表,空格是選擇列表,左右移動選擇退出選項 3.首次編譯執行清除 在 lichee linux3.4...