原始碼分析:
總結
hashmap map = new hashmap();/i預設情況下,先不建立長度為16的陣列
當首次呼叫map.put()時,再建立長度為16的陣列
陣列為node型別,在jdk7中稱為entry型別
形成鍊錶結構時,新新增的key-value對在鍊錶的尾部(七上八下)
當陣列指定索引位置的鍊錶長度》8時,且map中的陣列的長度》64時,此索引位置上的所有key-value對使用紅黑樹進行儲存。
將k和v封裝到node物件當中(節點)
呼叫k的hashcode()方法得出hash值
通過雜湊表函式/雜湊演算法,將hash值轉換成陣列的下標。做法為hash值對陣列長度取模,當n為2的冪時,等效為hash&(n-1)。這也是為什麼map中陣列長度取為2的整數次冪。
呼叫k的hashcode()方法得出雜湊值,通過雜湊演算法轉換成陣列下標。
通過陣列下標快速定位到某個位置上。
如果這個位置上什麼都沒用,則返回null。
如果這個位置上有單向列表,那麼就會用引數k和單向鍊錶上的每乙個節點的k進行equals比較
hash陣列儲存該node節點的引用,當發生了hash碰撞,解決衝突的辦法為鍊錶法/紅黑樹,也即節點串成乙個鍊錶
static
class
node
implements
map.entry
public
final k getkey()
public
final v getvalue()
public
final string tostring()
public
final
inthashcode()
public
final v setvalue
(v newvalue)
public
final
boolean
equals
(object o)
return
false;}
}
//初始化陣列大小
static
final
int default_initial_capacity =
1<<4;
// aka 16
/*** the maximum capacity, used if a higher value is implicitly specified
* by either of the constructors with arguments.
* must be a power of two <= 1<<30.
*/static
final
int maximum_capacity =
1<<30;
/*** the load factor used when none specified in constructor.
*///負載因子
static
final
float default_load_factor =
0.75f
;//當鍊表數目超過該值,轉換為紅黑樹
static
final
int treeify_threshold =8;
//當紅黑樹節點小於該數目,退化為鍊錶
static
final
int untreeify_threshold =6;
//當陣列數目大於該值,鍊錶與紅黑樹的轉換才優先考慮
static
final
int min_treeify_capacity =
64;
transient node
table;
public
hashmap
(int initialcapacity,
float loadfactor)
//傳入乙個初始容量,預設負載因子0.75
public
hashmap
(int initialcapacity)
//無引數,負載因子預設0.75
public
hashmap()
//傳入乙個map的物件
public
hashmap
(map<
?extendsk,
?extends
v> m)
public v put
(k key, v value)
----
----
----
----
----
----
----
----
----
----
----
----
----
----
--static
final
inthash
(object key)
----
----
----
----
----
----
----
----
----
----
----
----
----
----
--final v putval
(int hash, k key, v value,
boolean onlyifabsent,
boolean evict)
//說明找到的元素key一樣,進行替換,break跳出迴圈即可
if(e.hash == hash &&
((k = e.key)
== key ||
(key != null && key.
equals
(k))))
break
; p = e;}}
----
----
----
----
----
----
----
----
----
----
----
----
----
----
--//e不等於null,說明找到了乙個與你插入元素完全一致的,進行替換
if(e != null)}--
----
----
----
----
----
----
----
----
----
----
----
----
----
----
//modcount:表示雜湊表結構被修改次數,替換元素不算次數
++modcount;
//插入新元素,size自增,如果自增大於擴容閾值,則觸發擴容if(
++size > threshold)
resize()
;afternodeinsertion
(evict)
;return null;
}
public v get
(object key)
----
----
----
----
----
----
----
----
----
----
----
----
----
----
--final node
getnode
(object key)
while
((e = e.next)
!= null);}
}return null;
}
構造hash表時,如果不指明初始大小,預設大小為16(即node陣列大小16),如果node陣列中的元素達到(填充比*node.length)重新調整hashmap大小 變為原來2倍大小,擴容很耗時
首先有乙個每個元素都是鍊錶(可能表述不準確)的陣列,當新增乙個元素(key-value)時,就首先計算元素key的hash值,以此確定插入陣列中的位置,但是可能存在同一hash值的元素已經被放在陣列同一位置了,這時就新增到同一hash值的元素的後面,他們在陣列的同一位置,但是形成了鍊錶,同一各煉表上的hash值是相同的,所以說陣列存放的是鍊錶。而當鍊錶長度太長時,鍊錶就轉換為紅黑樹,這樣大大提高了查詢的效率。
當鍊表陣列的容量超過初始容量的0.75時,再雜湊將鍊錶陣列擴大2倍,把原鍊錶陣列的搬移到新的陣列中
HashMap底層原始碼分析
static final int default initial capacity 1 4 aka 16表示1向左移4位,2的4次方 static final int maximum capacity 1 30 hashmap陣列的最大容量 static final float default lo...
HashMap底層原始碼解析
目錄 一 分析hashmap的資料結構 1.使用陣列儲存,加快訪問速度 2.陣列中的鍊錶,解決hash衝突 3.使用紅黑樹優化鍊錶,防止大量hash衝突 二 hashmap主要原始碼解讀 三 總結 在看原始碼之前,了解一下它的資料結構和執行過程,才能更快更加有效率的讀懂原始碼。hashmap實際儲存...
HashMap底層原始碼剖析
陣列 單向鍊錶 紅黑樹 陣列 陣列每一項都是乙個鍊錶,其實就是陣列和鍊錶的結合體 單向鍊錶 當法神hash碰撞時,首先會找到陣列對應位置,然後1.8採用尾插入法 1.7採用頭插入法 形成乙個單項鍊表結構 紅黑樹 當陣列中每項的鍊錶長度大於8時,會轉換為紅黑樹 hash碰撞 不同的key可能會產生相同...