實現的介面是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
節點。這個節點裡是在hashmap
的node
節點上新增了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...