HashMap元素插入和擴容

2021-10-10 23:18:08 字數 4224 閱讀 3260

從jdk1.8開始hashmap的儲存結構變成了陣列+鍊錶+紅黑樹,單鏈表中元素個數超過指定閾值,會轉化為紅黑樹結構儲存(提高查詢效率);

從1.7到1.8,在hash衝突的時候,鍊錶的插入將頭插法改為尾插法,防止在高併發的情緒出現迴圈鍊錶;

hashmap的預設陣列大小為16,代表hash陣列的長度;

預設的載入因子是0.75,代表存入元素大於陣列大小*載入因子就進行擴容;

hashmap是執行緒不安全的,方法都未使用synchronized關鍵字;

允許key和value值為null(預設hash演算法的情況下,放在資料的0號位置);

//預設初始大小:16

static

final

int default_initial_capacity =

1<<4;

//最大容量:2^30

static

final

int maximum_capacity =

1<<30;

//預設的記載因子:0.75

static

final

float default_load_factor =

0.75f

;//鍊錶的長度大於8,就需要將對應的鍊錶轉為紅黑樹

static

final

int treeify_threshold =8;

//紅黑樹的節點數小於6,就需要將其轉為鍊錶

static

final

int untreeify_threshold =6;

//將鍊錶轉為紅黑樹的另乙個前提條件,總元素樹大於64

static

final

int min_treeify_capacity =

64;

static

final

inthash

(object key)

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

//掃瞄發現,鍊錶中存在key一致的元素,結束迴圈

break

; p = e;}}

if(e != null)

}++modcount;if(

++size > threshold)

//新增之後,元素個數是否大於閾值,進行擴容

resize()

;afternodeinsertion

(evict)

;return null;

}

final node

resize()

elseif(

(newcap = oldcap <<1)

< maximum_capacity &&

oldcap >= default_initial_capacity)

//長度沒有超過maximum_capacity,陣列長度擴容一倍

newthr = oldthr <<1;

// 新增閾值,擴容一倍

}else

if(oldthr >0)

// 陣列為空,指定了新增閾值

newcap = oldthr;

else

if(newthr ==0)

threshold = newthr;

//擴容後的新增閾值

@suppresswarnings()

node

newtab =

(node

)new

node

[newcap]

;//擴容之後的陣列

table = newtab;

if(oldtab != null)

else

}while

((e = next)

!= null);if

(lotail != null)

if(hitail != null)}}

}}return newtab;

}

首次插入資料,初始化陣列

未指定大小

1.通過無參構造建立

hashmap

map =

newhashmap

<

>()

;

2.put()方法中新增元素,發現table==null,呼叫resize()初始化陣列

if

((tab = table)

== null ||

(n = tab.length)==0

) n =

(tab =

resize()

).length;

3.resiz()方法分支

int oldcap =

(oldtab == null)?0

: oldtab.length;

//初始化,為0

int oldthr = threshold;

//初始化,為0

//執行的分支**

// 陣列為空,未指定了新增閾值,採用預設的數值,16*0.75=12

newcap = default_initial_capacity;

newthr =

(int

)(default_load_factor * default_initial_capacity)

;threshold = newthr;

//擴容後的新增閾值

@suppresswarnings()

node

newtab =

(node

)new

node

[newcap]

;//擴容之後的陣列

table = newtab;

return newtab;

指定了初始化大小

1.通過有參構造建立

hashmap

hashmap =

newhashmap

<

>(7

);//指定初始化大小

2.put()方法中新增元素,發現table==null,呼叫resize()初始化陣列

if

((tab = table)

== null ||

(n = tab.length)==0

) n =

(tab =

resize()

).length;

3.resiz()方法分支

int oldcap =

(oldtab == null)?0

: oldtab.length;

//初始化,為0

int oldthr = threshold;

//初始化,為大於指定大小的最小2次冪

int newcap, newthr =0;

// 陣列為空,指定了新增閾值

newcap = oldthr;

if(newthr ==0)

threshold = newthr;

//擴容後的新增閾值

@suppresswarnings()

node

newtab =

(node

)new

node

[newcap]

;//擴容之後的陣列

table = newtab;

return newtab;

非首次插入擴容

hashMap擴容機制

擴容時空間大小變化 hashmap中,雜湊桶陣列table的長度length大小必須為2的n次方 一定是合數 這是一種非常規的設計,常規的設計是把桶的大小設計為素數。相對來說素數導致衝突的概率要小於合數,具體證明可以參考 hashtable初始化桶大小為11,就是桶大小設計為素數的應用 hashta...

HashMap擴容機制

當map元素容量超過設定的閾值threshold capacity loadfactor時進行擴容,如下圖所示 原理 建立更大容量的新陣列,重新計算每個元素在新陣列中的位置進行遷移。缺點 每個元素需要重新計算hash 鍊錶中元素順序每次遷移後被倒置 原理 在擴充hashmap的時候,不需要像jdk1...

HashMap擴容閾值

閾值 容量 x 負載因子,假設當前hashmap的容量是 16,負載因子是預設值 0.75,那麼當 size 到達16 x 0.75 12 的時候,就會觸發擴容。ps 初始化時,若指定的初始大小不是按照要求來的 則取數字最近的符合規則的數字 將傳過來的引數值轉換為最接近 且大於等於指定引數的 2 的...