想必經曆過面試的人很多都能被問到這個問題,當然小編也不例外,今天就給大家剖析一下HashMap在jdk1.8中的結構及其使用,分享在這,從中自己也在學習,不斷積累技術和大家一起分享。
一:概述
HashMap最早在jdk1.2中就存在了,HashMap繼承自父類(AbstractMap),實作了Map、Cloneable、Serializable接口,底層思想是基于雜湊演算法實作的,HashMap可以用null作為鍵,也可以用null作為值,當存儲的鍵為null時,對應計算的結果是0,用0作為鍵值的,HashMap不是線程安全的,如果使用HashMap要滿足線程安全,可以使用Collectio類的的synchronizedMap方法使HashMap具有線程安全的能力,或者使用ConcurrentHashMap類。
一:資料的存儲結構
在jdk1.7中的HashMap中的資料結構是數組+單連結清單的組合,使用連結清單處理hash值沖突的元素,而存在的問題就是當hash鍵值相等的情況較多時,都會将值儲存在一個單連結清單上,也就是其中的一個桶中,導緻通過key值去查找效率很低,是以在jdk1.8中,HashMap采用了數組+連結清單+紅黑樹來實作,這在結構上與jdk 1.7最大的不同,而在jdk1.8中,如果hash鍵值沖突較多時,單連結清單的長度超過規定的臨界值(8)時,就會将連結清單轉換成紅黑樹的結構存儲,這樣就能高效的查詢,提高HashMap的查詢效率。
1. HashMap成員變量:
* The default initial capacity - MUST be a power of two.
* 預設HashMap初始化的容量為16,且長度必須為2的幂等
*/
static final int DEFAULT_INITIAL_CAPACITY = 16;
/**
* The table, resized as necessary. Length MUST Always be a power of two.
* 數組是存儲HashMap的連結清單表頭
*/
transient Entry<K,V>[] table;
/** 最大初始容量,2^30 */
static final int MAXIMUM_CAPACITY = 1 << 30;
/** 負載因子,預設0.75,負載因子越小,hash沖突機率越低 */
static final float DEFAULT_LOAD_FACTOR = 0.75f;
/** 初始化一個Entry的空數組 */
static final Entry<?,?>[] EMPTY_TABLE = {};
/** HashMap實際存儲的元素個數 */
transient int size;
/** 臨界值(HashMap 實際能存儲的大小),公式為(threshold = capacity * loadFactor) */
int threshold;
/** 負載因子 */
final float loadFactor;
/** HashMap的結構被修改的次數,用于疊代器 */
transient int modCount;
2:HashMap的數組結構

圖1
3:紅黑樹結構及性質介紹
紅黑樹其實就是一種自平衡的二叉查找樹,他這個自平衡的特性就是針對HashMap中連結清單可能會很長,做出的優化。紅黑樹是每個節點都帶有顔色屬性的二叉查找樹,顔色或紅色或黑色。在二叉查找中有的性質外,紅黑樹也有自己的特點:
特點1. 節點都是紅色或黑色,是以稱為紅黑樹。
特點2. 樹的根節點是黑色。
特點3. 每個葉節點(NIL節點,空節點)是黑色的。
特點4. 每個紅色節點的兩個子節點都是黑色。(從每個葉子到根的所有路徑上不能有兩個連續的紅色節點)
特點5. 從任一節點到其每個葉子的所有路徑都包含相同數目的黑色節點。
static final class TreeNode<k,v> extends LinkedHashMap.Entry<k,v> {
TreeNode<k,v> parent; // 父節點
TreeNode<k,v> left; //左子樹
TreeNode<k,v> right;//右子樹
TreeNode<k,v> prev; // needed to unlink next upon deletion
boolean red; //顔色屬性
TreeNode(int hash, K key, V val, Node<k,v> next) {
super(hash, key, val, next);
}
4:HashMap的擴容機制