LinkedHashMap 原始碼分析

2021-08-17 16:22:37 字數 2970 閱讀 4113

實現的介面是map

繼承的是hashmap這個就比較熟悉了,事實上我們會看到linkedhashmap**量非常的少,主要就是因為他繼承的hashmap,繼承了大多數的操作。 仔細一點的都會發現hashmap裡面有非常多的空白方法,這些方法其實是模板方法,為了讓繼承hashmap的類重寫一些自己的特性。而不破壞**結構。

1. 基本字段

hashmap的基礎上他新增了三個字段,這三個欄位都非常重要,首先就是關於雙向鍊錶的兩個字段 以及決定是否進行 lru 的標誌位。

// 雙向鍊錶的頭結點

transient linkedhashmap.entryhead;

// 雙向鍊錶的尾節點

transient linkedhashmap.entrytail;

// 決定是否進行 lru 演算法

final

boolean accessorder;

2. entry 節點

可能看過前面關於hashmap原始碼分析的都清楚,裡面有乙個treenode節點,他繼承的就是linkedhashmap中的entry節點。這個節點裡是在hashmapnode節點上新增了before 和 after,也就是用來構造雙向鍊錶的指標。

ctor-5 最重要的能實現 lru 的是設定 accessorder 的那個

afternoderemoval

afternodeinsertion

afternodeaccess

containsvalue

getremoveeldestentry

這個類有 5 個構造方法,一開始我以為和hashmap一樣只有四個,後來又找到乙個隱藏的比較深的方法,也是實現 lru 最重要的乙個方法。

那麼我們重點分析最後乙個特殊的方法,前面幾個方法我們都見過和hashmap中的差不多,就是多了乙個設定accessorder=false的操作。最後那個方法如果我們設定了accessorder=true那麼我們在訪問乙個元素的時候,這個元素會自動的排到雙向鍊錶的結尾。也就是所謂的 lru。

既然提到構造方法我們順帶說一下reinitialize方法這個方法是設定了頭結點和尾節點。這些方法是在clone反序列化的時候使用的。

public

linkedhashmap(int initialcapacity,

float loadfactor,

boolean accessorder)

// 初始化雙鏈表

void reinitialize()

這個方法比較簡單,也是模板方法,裡面的主要作用就是修改一下雙向鍊錶,從而達到刪除乙個節點的作用。

// 這個方法還 ok 就是修改一下雙向指標

void afternoderemoval(nodee)

在插入節點以後,如果說我們實現的 lru 演算法是需要刪除一些舊的節點時候,這個方法就會在插入節點完成之後自動刪除舊節點。刪除的邏輯是removeeldestentry方法決定的,如果要啟用刪除這個方法裡面做刪除邏輯,並且返回true。這裡沒有任何實現!

// 插入新的節點以後,如果說定義了刪除老元素的方法,這個方法返回 true 的話就直接刪除原來的舊元素 注意老元素是在頭部  所以刪除頭部的元素即可

// 在這個地方是不做人事事情的 removeeldestentry 返回了 false

void afternodeinsertion(boolean evict)

}

在節點訪問以後,如果說我們沒有開啟 lru 演算法,那沒什麼關係,訪問了以後順序不變,而如果accessorder=true那麼訪問的元素必須要放到雙向鍊錶的結尾。

// 如果accessorder 為 true,也就是支援 lru 演算法,那麼就把這個元素先從雙向鍊錶中刪除(在陣列中的位置不變),然後插到鍊錶的頭部作為最新的元素

void afternodeaccess(nodee)

tail = p;

++modcount;

}}

重寫了父類的方法,主要是因為有了 雙向鍊錶的支援,遍歷會更快。

// 重寫了 containsvalue 因為有了雙鏈表了遍歷起來更方便

public

boolean

containsvalue(object value)

return

false;

}

get 方法屬於訪問元素,還是 lru 的問題、

// 重寫了,獲取元素以後,如果用了 lru 需要重新排列該元素的位置

public v get(object key)

空實現。

// 這個方法是用來被覆蓋的,也就是子類來用,本類用不著。

// 如果有必要,則刪除掉該近期最少使用的節點,

// 這要看對removeeldestentry的覆寫,由於預設為false,因此預設是不做任何處理的。

protected

boolean

removeeldestentry(map.entryeldest)

其實在理解這個容器的時候我們就把他當做hashmap加上乙個無關的雙向指標即可。 然後注意一下他的 lru 演算法的利用!

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...