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, floatloadfactor)
public weakhashmap(int
initialcapacity)
public
weakhashmap()
public weakhashmap(map<? extends k, ? extends v>m)
put方法:
publicv 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(intnewcapacity)
entry
newtable =newtable(newcapacity);
transfer(oldtable, newtable);
table =newtable;
if (size >= threshold / 2
) else
}
private void expungestaleentries()prev = p;
p = next;}}
}}
privatevoid 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是乙個抽象類,我們需要建立子...