本文是基於Java 8
的HashMap
進行分析,主要是介紹HashMap
中的成員變量和類變量的用途,以及分析HashMap
的數據結構。數組
在HashMap
中存在多個成員變量和類變量,搞清楚它們的用途有助於咱們更深刻了解HashMap
,下面是它們的介紹:緩存
/** * 默認的初始容量,值爲2的4次方 */ static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // 衆所周知是16 /** * 最大容量 */ static final int MAXIMUM_CAPACITY = 1 << 30; /** * 默認的負載因子 */ static final float DEFAULT_LOAD_FACTOR = 0.75f; /** * 將鏈表轉化爲紅黑樹的閾值,當鏈表節點數大於或等於該閾值-1則轉化爲紅黑樹 */ static final int TREEIFY_THRESHOLD = 8; /** * 將紅黑樹轉化爲鏈表的閾值,當紅黑樹的節點小於該閾值時轉化爲鏈表 */ static final int UNTREEIFY_THRESHOLD = 6; /** * 容許進行鏈表轉化爲紅黑樹的閾值,只有散列表大小大於或等於該值才能進行紅黑樹轉化 */ static final int MIN_TREEIFY_CAPACITY = 64; /** * HashMap中存儲數據的數組,也稱爲散列表。 * 長度爲2的N次冪 */ transient Node<K,V>[] table; /** * 緩存entrySet()方法的值 */ transient Set<Map.Entry<K,V>> entrySet; /** * Map中鍵值對的個數 */ transient int size; /** * HashMap數據結構被改變的次數,通常是指散列表的長度改變、Node鏈表增長或者減小節點 * 這個參數是用於快速失敗機制 */ transient int modCount; /** * 下一次觸發調整大小(resize()方法)的閾值,通常爲容量乘以負載因子 */ int threshold; /** * 散列表的負載因子,用於計算擴容的閾值 */ final float loadFactor;
HashMap
使用拉鍊法解決哈希表中存在的哈希衝突問題,因此HashMap
底層是用以Node
(Java 7
名稱是Entry
)組成的鏈表爲元素的數組table
來存儲鍵值對,每一個Node
就是一個鍵值對對象。table
稱呼爲散列表。數據結構
而table
對應的是散列表,是由於不管是存儲仍是讀取鍵值對的時候,都會對key
進行hash%table.length
運算來進行散列表的命中,而後操做命中的索引對應的Node
鏈表(仍是會比較key
和hash
)。優化
以上爲Java 8
以前版本的HashMap
的實現,而Java 8
進行了優化:就是當鏈表節點數超過閾值TREEIFY_THRESHOLD(8)
時,則會將鏈表轉化爲紅黑樹。spa
若是隻是使用文字描述的話會很難理解,因此下面會經過一幅圖展現:code