在JDK1.6,1.7中,HashMap的實現都是用基礎的“拉鏈法”去實現,即數組+鏈表的形式。如下圖:通過不同的hash值,來對數據進行分配存儲。
關於HashMap的Entry長度,可以參考http://wiki.jikexueyuan.com/project/java-collection/hashmap.html
簡要來說,要保證初始化時 HashMap 的容量總是 2 的 n 次方,即底層數組的長度總是為 2 的 n 次方。
那么 HashMap 什么時候進行擴容呢?當 HashMap 中的元素個數超過數組大小 *loadFactor
時,就會進行數組擴容,loadFactor的默認值為 0.75,這是一個折中的取值。也就是說,默認情況下,數組大小為 16,那么當 HashMap 中元素個數超過 16*0.75=12
的時候,就把數組的大小擴展為 2*16=32
,即擴大一倍,然后重新計算每個元素在數組中的位置。
HashMap 包含如下幾個構造器:
- HashMap():構建一個初始容量為 16,負載因子為 0.75 的 HashMap。
- ashMap(int initialCapacity):構建一個初始容量為 initialCapacity,負載因子為 0.75 的 HashMap。
- HashMap(int initialCapacity, float loadFactor):以指定初始容量、指定的負載因子創建一個 HashMap。
在JDK1.8中對HashMap的源碼進行了優化,在jdk7中,HashMap處理“碰撞”的時候,都是采用鏈表來存儲,當碰撞的結點很多時,查詢時間是O(n)。
在jdk8中,HashMap處理“碰撞”增加了紅黑樹這種數據結構,當碰撞結點較少時,采用鏈表存儲,當較大時(>8個),采用紅黑樹(特點是查詢時間是O(logn))存儲(有一個閥值控制,大於閥值(8個),將鏈表存儲轉換成紅黑樹存儲)
關於紅黑樹的介紹,可以參考