WeakHashMap原始碼分析

2021-09-19 04:44:38 字數 3072 閱讀 1471

weakhashmap是一種弱引用map,內部的key會儲存為弱引用,

當jvm gc的時候,如果這些key沒有強引用存在的話,會被gc**掉,

下一次當我們操作map的時候會把對應的entry整個刪除掉,基於這種特性,weakhashmap特別適用於快取處理。

//初始化容量

private

static final int default_initial_capacity = 16

; //最大容量

private

static final int maximum_capacity = 1

<< 30

; //擴容因子

private

static final float default_load_factor = 0.75f

;//內部類

entry

table;

//長度

private

intsize;

//擴容銀子

private

intthreshold;

//裝載因子

private final float

loadfactor;

//引用佇列

private final referencequeuequeue = new referencequeue<>();

//修改次數

int modcount;

(1)容量

容量為陣列的長度,亦即桶的個數,預設為16,最大為2的30次方,當容量達到64時才可以樹化。

(2)裝載因子

裝載因子用來計算容量達到多少時才進行擴容,預設裝載因子為0.75。

(3)引用佇列

當弱鍵失效的時候會把entry新增到這個佇列中,當下次訪問map的時候會把失效的entry清除掉。

(4 ) entry為內部類

構造方法

public weakhashmap(int initialcapacity, float

loadfactor)

public weakhashmap(int

initialcapacity)

public

weakhashmap()

public weakhashmap(map<? extends k, ? extends v>m)

put方法:

public

v put(k key, v value)

}modcount++;

entry

e =tab[i];

tab[i] = new entry<>(k, value, queue, h, e);

if (++size >=threshold)

如果插入元素數量達到了句擴容至hash桶的兩倍大小

resize(tab.length * 2

);

return

null

; }

(1)計算hash;

這裡與hashmap有所不同,hashmap中如果key為空直接返回0,這裡是用空物件來計算的。

另外打散方式也不同,hashmap只用了一次異或,這裡用了四次,hashmap給出的解釋是一次夠了,而且就算衝突了也會轉換成紅黑樹,對效率沒什麼影響。

(2)計算在哪個桶中;

(3)遍歷桶對應的鍊錶;

(4)如果找到元素就用新值替換舊值,並返回舊值;

(5)如果沒找到就在鍊錶頭部插入新元素;

hashmap就插入到鍊錶尾部。

(6)如果元素數量達到了擴容門檻,就把容量擴大到2倍大小;

hashmap中是大於threshold才擴容,這裡等於threshold就開始擴容了。

擴容:

void resize(int

newcapacity)

entry

newtable =newtable(newcapacity);

transfer(oldtable, newtable);

table =newtable;

if (size >= threshold / 2

) else

}

private void expungestaleentries() 

prev = p;

p = next;}}

}}

private

void transfer(entry src, entry dest)

else

e =next;}}

}

(1)判斷舊容量是否達到最大容量;

(2)新建新桶並把元素全部轉移到新桶中;

(3)如果轉移後元素個數不到擴容門檻的一半,則把元素再轉移回舊桶,繼續使用舊桶,說明不需要擴容;

(4)否則使用新桶,並計算新的擴容門檻;

(5)轉移元素的過程中會把key為null的元素清除掉,所以size會變小;

expungestaleentries
()1)當key失效的時候gc會自動把對應的entry新增到這個引用佇列中;

(2)所有對map的操作都會直接或間接地呼叫到這個方法先移除失效的entry,比如gettable()、size()、resize();

(3)這個方法的目的就是遍歷引用佇列,並把其中儲存的entry從map中移除掉,具體的過程請看類注釋;

(4)從這裡可以看到移除entry的同時把value也一併置為null幫助gc清理元素,防禦性程式設計。

總結:(1)weakhashmap使用(陣列 + 鍊錶)儲存結構,並不是像hashmap一樣,有紅黑樹的加入;

(2)weakhashmap中的key是弱引用,gc的時候會被清除;

(3)每次對map的操作都會剔除失效key對應的entry;

(4)使用string作為key時,一定要使用new string()這樣的方式宣告key,才會失效,其它的基本型別的包裝型別是一樣的;

posted @

2019-04-17 13:12

動手的程式設計師 閱讀(

...)

編輯收藏

Cartographer原始碼篇 原始碼分析 1

在安裝編譯cartographer 1.0.0的時候,我們可以看到 主要包括cartorgarpher ros cartographer ceres sover三個部分。其中,ceres solver用於非線性優化,求解最小二乘問題 cartographer ros為ros平台的封裝,獲取感測器資料...

AbstractListView原始碼分析3

normal list that does not indicate choices public static final int choice mode none 0 the list allows up to one choice public static final int choice ...

Android AsyncTask原始碼分析

android中只能在主線程中進行ui操作,如果是其它子執行緒,需要借助非同步訊息處理機制handler。除此之外,還有個非常方便的asynctask類,這個類內部封裝了handler和執行緒池。本文先簡要介紹asynctask的用法,然後分析具體實現。asynctask是乙個抽象類,我們需要建立子...