1.儲存結構
內部包含了⼀個 entry 型別的陣列 entry table。transient entry table;
*(transient:表示不能被序列化)*entry型別儲存著鍵值對。它包含了四個字段, entry 是⼀個鍊錶。即陣列中的每個位置被當成⼀個桶,⼀個桶存放⼀個entry鍊錶。hashmap 使⽤拉鍊法來解決衝突,同⼀個鍊錶中存放雜湊值和雜湊桶取模運算結果相同的 entry。
2.常規操作
(1)final k getkey();
(2)final v getvalue();
(3)final v setvalue(v newvalue);
(4)final boolean equals(object o);
(5)final int hashcode();
(6)final string tostring();
static
class
entry
implements
map.entry
public
final k getkey()
public
final v getvalue()
public
final v setvalue
(v newvalue)
public
final
boolean
equals
(object o)
return
false;}
public
final
inthashcode()
public
final string tostring()
}
3.插入put操作(1)插入陣列是對hash值與雜湊表使用除留餘數的方法計算得到對應桶序號;
(2)插入時採用鍊錶的頭插法進行插入;
(3)hashmap 允許插⼊鍵為 null 的鍵值對。但是因為 null 的 hashcode() ⽅法,也就⽆法確定該鍵值對應桶下標,只能通過強制指定第 0 個桶存放鍵為 null 的鍵值對;
public v put
(k key, v value)
// 鍵為 null 單獨處理
if(key == null)
return
putfornullkey
(value)
;int hash =
hash
(key)
;// 確定桶下標
int i =
indexfor
(hash, table.length)
;// 先找出是否已經存在鍵為 key 的鍵值對,如果存在的話就更新這個鍵值對的值為 value
for(entry
e = table[i]
; e != null; e = e.next)
} modcount++
;// 插⼊新鍵值對
4.擴容設 hashmap 的 table ⻓度為 m,需要儲存的鍵值對數量為 n,如果雜湊函式滿⾜均勻性的要求,那麼每條鍊錶的⻓度⼤約為 n/m,因此查詢的複雜度為 o(n/m)。為了讓查詢的成本降低,應該使 n/m 盡可能⼩,因此需要保證 m 盡可能⼤,也就是說 table 要盡可能⼤。
(1)hashmap 採⽤動態擴容來根據當前的鍵值對數量來調整陣列長度,使得空間效率和時間效率都能得到保證。(hashmap擴容並不是等到陣列滿了才擴容,因為元素是插入到鍊錶中,永遠也不會滿,所以有乙個閾值–threshold,當等於它時就進行擴容操作)
(2)capacity一般為2的n次方,即使使用者傳入的不是2的n次方,它也可以⾃動地將傳⼊的容量轉換為 2 的n 次⽅。原因是除留餘數取模時採用的是位運算來代替取模運算,能夠極⼤降低重新計算桶下標操作的複雜度。(位運算只用於2進製,所以需要2的n次方);
(3)當需要擴容時,使⽤ resize() 實現,令 capacity 為原來的兩倍,擴容操作需要把oldtable 的所有鍵值對重新插入newtable 中,因此這⼀步是很費時的。
(4)當⼀個桶儲存的鍊錶⻓度⼤於等於 8 時會將鍊錶轉換為紅⿊樹。
引數含義
capacity
table 的容量⼤⼩,預設為 16。需要注意的是 capacity 必須保證為 2 的 n 次⽅。
size
鍵值對數量。
threshold
size 的臨界值,當 size ⼤於等於 threshold 就必須進⾏擴容操作。
loadfactor
裝載因⼦,table 能夠使⽤的⽐例,threshold = (int)(capacity* loadfactor)。
static
final
int default_initial_capacity =16;
static
final
int maximum_capacity =
1<<30;
static
final
float default_load_factor =
0.75f
;transient entry[
] table;
transient
int size;
int threshold;
final
float loadfactor;
transient
int modcount;
void
addentry
(int hash, k key, v value,
int bucketindex)
void
resize
(int newcapacity)
entry[
] newtable =
newentry
[newcapacity]
;transfer
(newtable)
; table = newtable;
threshold =
(int
)(newcapacity * loadfactor);}
void
transfer
(entry[
] newtable)
while
(e != null);}
}}
5.與 hashtable 的⽐較hashtable 使⽤ synchronized 來進⾏同步。
hashmap 可以插⼊鍵為 null 的 entry。
hashmap 的迭代器是 fail-fast 迭代器。
hashmap 不能保證隨著時間的推移 map 中的元素次序是不變的。
HashMap 學習總結
本文參考見 by chenssy 知識點 1.hashmap的三個建構函式 hashmap 預設初始容量為16,預設載入因子是0.75 hashmap int initialcapacity 指定初始容量 但預設載入因子為0.75 hashmap int initialcapacity,float ...
HashMap學習總結
答 雜湊表又稱雜湊表是一種k value鍵值對對應關係的資料結構,它通過乙個關鍵碼k,經過雜湊函式,能找到存在陣列上的記錄,查詢速度塊。答 它是底層主幹是陣列 雜湊表的主幹是陣列 陣列裡的每個元素都是煉表頭。到了jdk8,增加了紅黑樹結構,所以,總的來說陣列 鍊錶 紅黑樹。答 hashmap有雜湊表...
HashMap知識總結
問題5 說說hashmap是如何進行擴容的可以嗎?問題6 那hashcode和equals在hashmap中是怎麼用的?jdk1.7的時候使用的是陣列 單鏈表的資料結構。但是在jdk1.8及之後時,使用的是陣列 鍊錶 紅黑樹的資料結構 當鍊表的深度達到8時,也就是預設閾值,會自動擴容,把鍊錶轉換成紅...