以jdk1.8為例,hashmap是乙個用於儲存key-value鍵值對的集合,每乙個鍵值對是乙個node(jdk1.7叫做entry)。後台是用乙個node陣列來存放資料,這個node陣列就是hashmap的主幹。
這裡我們主要來分析hashmap的get和put方法。
public v put(k key, v value)
final v putval(int hash, k key, v value, boolean onlyifabsent,
boolean evict)
//這裡表示鍊錶中某個節點的key與即將插入的key相等,就跳出迴圈等待覆蓋
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;}}
//這裡表示有節點的key與新的key相等,那麼就覆蓋
if (e != null)
} ++modcount;
//插入完之後,如果導致size超過了預設的閾值,就進行擴容(1.7是插入前判斷,1.8是插入後判斷)
if (++size > threshold)
resize();
afternodeinsertion(evict);
return null;
}
擴容步驟:
1、建立乙個原陣列兩倍大小的新陣列,並且把閾值擴大一倍。
2、遍歷原陣列,進行資料遷移。分為紅黑樹和鍊錶兩種情況。
好了,擴容部分就不展開**詳細說明,接下來進入get方法,相較於put方法就沒那麼複雜了,且**量也比較少
public v get(object key)
final nodegetnode(int hash, object key) while ((e = e.next) != null);
}} return null;
}
注意:
1、hashmap底層就是用乙個個的node來儲存單個資料,每個node有hash值、key、value、及指向下乙個node的引用(next)。node陣列中就是所有鍊錶的頭節點。
2、當出現hash衝突的情況,原node的next就會指向新插入的node,也就是形成了鍊錶。
3、每次擴容的長度必須是2的冪,因為,根據key的hash值計算出的陣列索引應盡量不要重複,實現均勻分布,均勻分布的話大部分查詢的資料都是以陣列的形式查詢,就不會蛻變成煉表,而陣列的查詢效率比煉表高很多。
4、影響擴容的因素有兩個:陣列的長度(default_initial_capacity)和負載因子(default_load_factor),當這兩個相乘大於等於當前hashmap的size時,就進行擴容
5、擴容在併發情況下可能會形成鍊錶環,存在併發安全問題,這點需要注意
6、當鍊表的節點超過8個時,會轉成紅黑樹,鍊錶的時間複雜度為o(n),而紅黑樹為o(logn)
hashMap 原始碼解析
這幾天跳槽 被人問得最多的問題就是基礎方面的知識.當時學習的時候有點囫圇吞棗.現在回頭把這些基本的集合類原始碼都仔細閱讀下 hashmap 用的是最頻繁的.所以問得也最多了.initcapacity 初始化的容量 loadfacotr 負載因子 主要用來計算threshold的值 threshold...
HashMap原始碼解析
預設字段 static final int default initial capacity 1 4 預設node的陣列長度 16 static final int maximum capacity 1 30 陣列的最大長度 2 30 static final float default load ...
Hashmap原始碼解析
話不多說,直接看hashmap的put 方法原始碼 這是jdk1.8的原始碼 與1.7有所不同。final v putval int hash,k key,v value,boolean onlyifabsent,boolean evict if e.hash hash k e.key key ke...