LinkedHashMap及其應用LruCache

2021-08-26 15:16:28 字數 4548 閱讀 9069

linkedhashmap

簡介linkedhashmap是hashmap的子類;在hashmap的基礎上又用雙向鍊錶來實現的;換句話說:linkedhashmap的所有元素不僅滿足hashmap的資料結構,同時滿足linkedlist的結構,維護著這兩套實現方式;

linkedhashmap類主要是維護雙向鍊錶,其他的工作主要還是在hashmap中實現;

linkedhashmapentry

static

class

linkedhashmapentry

extends

hashmap.node

}

主要變數

transient linkedhashmapentry

head;頭結點,雙鏈表中存在最久的節點;

transient linkedhashmapentry

tail;尾結點,鍊錶中剛加入的節點;

final

boolean accessorder;是否根據訪問順序,改變雙向鍊錶的順序;預設為false

;實現lrucache演算法的主要實現;

linkedhashmap主要實現hashmap的三個空方法

// callbacks to allow linkedhashmap post-actions

void

afternodeaccess

(node

p)void

afternodeinsertion

(boolean evict)

void

afternoderemoval

(node

p)

put()方法

put()方法,還是呼叫hashmap的put()方法,主要區別在於putval()中newnode()方法,會呼叫linkedhashmap自己的newnode()方法;其他都一樣,最後likedhashmap方法實現了;

public v put

(k key, v value)

final v putval

(int hash, k key, v value,

boolean onlyifabsent,

boolean evict)

if(e.hash == hash &&

((k = e.key)

== key ||

(key != null && key.

equals

(k))))

break

; p = e;}}

if(e != null)

}++modcount;if(

++size > threshold)

resize()

;//3 不存在的話,hashmap插入新節點,linkedhashmap有具體的實現;

afternodeinsertion

(evict)

;return null;

}

linkedhashmap的newnode()方法;

//建立新節點,插入雙鏈表尾後,並返回該節點;

node

newnode

(int hash, k key, v value, node

e)//在鍊錶尾插入新節點;

private

void

linknodelast

(linkedhashmapentry

p)}

afternodeaccess():如果根據訪問順序排序,並且訪問的節點不是尾結點;將當前節點從鍊錶中刪除,再插入到尾結點後;

void

afternodeaccess

(node

e)//為尾結點重新賦值;

tail = p;

++modcount;

}}

afternodeinsertion():刪除雙向鍊錶中最老的節點即頭結點;預設情況下removeeldestentry()返回false;lrucache類會重寫,返回true;

void

afternodeinsertion

(boolean evict)

}

get()方法

get():獲取對應的值,並且如果是根據訪問排序,在雙向鍊錶中先刪除當前節點e,再插入到鍊錶尾節點後;改變雙向鍊錶的順序;

public v get

(object key)

remove()方法

remove():完全呼叫hashmap的remove()方法,在刪除之後呼叫afternoderemoval(),將當前節點從雙向鍊錶中刪除;

void

afternoderemoval

(node

e)

lrucache

內部使用linkedhashmap作為成員變數儲存元素;key,value都不能為null;根據linkedhashmap的雙鏈表和是否根據訪問順序排序特性來實現的;主要用於載入框架根據最近最少使用演算法,刪除不常用的,節約空間;

初始化

lrucache

lrucache =

newlrucache

(10)//值被替換或者被刪除

@override

protected

void

entryremoved

(boolean evicted, string key, string oldvalue, string newvalue)

};

put()方法:不存在key對應的節點,建立新的節點,加在雙鏈錶鏈尾;存在的話,將值替換;

public

final v put

(k key, v value)

v previous;

synchronized

(this)}

//entryremoved 為空方法,重寫,手動釋放物件value;

if(previous != null)

//計算當前最大size

trimtosize

(maxsize)

;return previous;

}

trimtosize()方法:put()方法之後,判斷當前size是否大於maxsize,如果大於,刪除最近最少使用的元素(即從雙鏈表頭刪除頭結點)

public

void

trimtosize

(int maxsize)

if(size <= maxsize)

map.entry

toevict = map.

eldest()

;if(toevict == null)

key = toevict.

getkey()

; value = toevict.

getvalue()

; map.

remove

(key)

; size -=

safesizeof

(key, value)

; evictioncount++;}

entryremoved

(true

, key, value, null);}

}

get()方法:存在key對應的節點,直接返回對應的value;不存在,呼叫create(key)方法,該方法預設情況下,返回null;也可以創協create()方法,自己實現;

public

final v get

(k key)

v mapvalue;

synchronized

(this

) misscount++;}

//create過程非同步

v createdvalue =

create

(key);if

(createdvalue == null)

//create()返回的不為null

synchronized

(this

)else}if

(mapvalue != null)

else

}

remove():存在key對應的節點,刪除,並減去size;

public

final v remove

(k key)

v previous;

synchronized

(this)}

if(previous != null)

return previous;

}

所有的分析內容到此結束了。如有問題,請多指教,謝謝!

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

LinkedHashMap 實現總結

繼承於hashmap,定義了新的內部類entry用於實現雙向鍊錶儲存記錄的插入或訪問順序 accessorder用於指示鍊錶儲存記錄採用的順序,true為訪問順序,false為插入順序 加入新的記錄時需要更新鍊錶,訪問記錄時需要更新鍊錶 更具accessorder值判斷是否實際更新 removeel...