LinkedHashMap的實現原理

2021-09-07 17:59:37 字數 3150 閱讀 8471

1. linkedhashmap概述:

linkedhashmap是map介面的雜湊表和鏈結列表實現,具有可預知的迭代順序。此實現提供所有可選的對映操作,並允許使用null值和null鍵。此類不保證對映的順序,特別是它不保證該順序恆久不變。

linkedhashmap實現與hashmap的不同之處在於,後者維護著乙個執行於所有條目的雙重鏈結列表。此鏈結列表定義了迭代順序,該迭代順序可以是插入順序或者是訪問順序。

注意,此實現不是同步的。如果多個執行緒同時訪問鏈結的雜湊對映,而其中至少乙個執行緒從結構上修改了該對映,則它必須保持外部同步。

2. linkedhashmap的實現:

對於linkedhashmap而言,它繼承與hashmap、底層使用雜湊表與雙向鍊錶來儲存所有元素。其基本操作與父類hashmap相似,它通過重寫父類相關的方法,來實現自己的鏈結列表特性。下面我們來分析linkedhashmap的源**:

1) entry元素:

linkedhashmap採用的hash演算法和hashmap相同,但是它重新定義了陣列中儲存的元素entry,該entry除了儲存當前物件的引用外,還儲存了其上乙個元素before和下乙個元素after的引用,從而在雜湊表的基礎上又構成了雙向鏈結列表。看源**:

1

/**

2* 雙向鍊錶的表頭元素。 3*/

4private transient entryheader; 56

/**

7* linkedhashmap的entry元素。 89

*/10

private

static

class entryextends hashmap.entry

2) 初始化:

public linkedhashmap(int initialcapacity, float

loadfactor)

1

public hashmap(int initialcapacity, float

loadfactor)

我們已經知道linkedhashmap的entry元素繼承hashmap的entry,提供了雙向鍊錶的功能。在上述hashmap的構造器

中,最後會呼叫init()方法,進行相關的初始化,這個方法在hashmap的實現中並無意義,只是提供給子類實現相關的初始化呼叫。

linkedhashmap重寫了init()方法,在呼叫父類的構造方法完成構造後,進一步實現了對其元素entry的初始化操作。

void

init()

3) 儲存:

linkedhashmap並未重寫父類hashmap的put方法,而是重寫了父類hashmap的put方法呼叫的子方法void addentry(int hash, k key, v value, int bucketindex) 和void createentry(int hash, k key, v value, int bucketindex),提供了自己特有的雙向鏈結列表的實現。

1

void addentry(int hash, k key, v value, int

bucketindex) else

13} 14

15void createentry(int hash, k key, v value, int

bucketindex)

2324

private

void addbefore(entryexistingentry)

4) 讀取:

linkedhashmap重寫了父類hashmap的get方法,實際在呼叫父類getentry()方法取得查詢的元素後,再判斷當排序模式accessorder為true時,記錄訪問順序,將最新訪問的元素新增到雙向鍊錶的表頭,並從原來的位置刪除。由於的鍊錶的增加、刪除操作是常量級的,故並不會帶來效能的損失。

1

public v get

(object key)

1011

void recordaccess(hashmapm)

20 }

5) 排序模式:

linkedhashmap定義了排序模式accessorder,該屬性為boolean型變數,對於訪問順序,為true;對於插入順序,則為false。

private final boolean accessorder;

一般情況下,不必指定排序模式,其迭代順序即為預設為插入順序。看linkedhashmap的構造方法,如:

public linkedhashmap(int initialcapacity, float

loadfactor)

這些構造方法都會預設指定排序模式為插入順序。如果你想構造乙個linkedhashmap,並打算按從近期訪問最少到近期訪問最多的順序(即訪問順序)來儲存元素,那麼請使用下面的構造方法構造linkedhashmap:

public linkedhashmap(int

initialcapacity,

float

loadfactor,

boolean accessorder)

該雜湊對映的迭代順序就是最後訪問其條目的順序,這種對映很適合構建lru快取。linkedhashmap提供了removeeldestentry(map.entryeldest)方法,在將新條目插入到對映後,put和 putall將呼叫此方法。該方法可以提供在每次新增新條目時移除最舊條目的實現程式,預設返回false,這樣,此對映的行為將類似於正常對映,即永遠不能移除最舊的元素。

protected boolean removeeldestentry(map.entryeldest)

此方法通常不以任何方式修改對映,相反允許對映在其返回值的指引下進行自我修改。如果用此對映構建lru快取,則非常方便,它允許對映通過刪除舊條目來減少記憶體損耗。

例如:重寫此方法,維持此對映只儲存100個條目的穩定狀態,在每次新增新條目時刪除最舊的條目。

private

static final int max_entries = 100

; protected

boolean removeeldestentry(map.entry eldest)

LinkedHashMap原始碼分析及實現LRU演算法

ps 要先了解hashmap的實現原理hashmap原始碼分析 可以看到linkedhashmap繼承了hashmap,其實際是在hashmap基礎上,把資料節點連成乙個雙向鍊錶,遍歷的時候按鍊錶順序遍歷。小總結預設的linkedhashmap 的遍歷會按照插入的順序遍歷出來,hashmap則不保證...

LinkedHashMap簡單解析

原始碼版本1.7 本文參考 1 內部結構 節點的結構 整體結構 插入過程 1 從table的角度看,新的entry需要插入到對應的bucket裡,當有雜湊衝突時,採用頭插法將新的entry插入到衝突鍊錶的頭部。2 從header的角度看,新的entry需要插入到雙向鍊錶的尾部。刪除過程 1 從tab...

LinkedHashMap學習筆記

概述linkedhashmap資料結構相比較於hashmap來說,新增了雙向指標,分別指向前乙個節點 before和後乙個節點 after,從而將所有的節點已鍊錶的形式串聯一起來 hashmap裡面的方法在linkedhashmap進行了重寫 void afternodeaccess nodep v...