部分重要屬性
//存放key,value的陣列
transient node table;
//存放entry的set
transient set> entryset;
//hashmap的大小 預設16
transient int size;
//修改次數
transient int modcount;
//擴擴容閾值capacity * load factor
int threshold;
//擴容係數 預設0.75
final float loadfactor;
//node內部類
static class nodeimplements map.entry
public final k getkey()
public final v getvalue()
public final string tostring()
public final int hashcode()
public final v setvalue(v newvalue)
public final boolean equals(object o)
return false;
}}
hash函式以及hash槽位計算
static final int hash(object key)
final nodegetnode(int hash, object key) while ((e = e.next) != null);}}
return null;
}
hash函式對key的hashcode進行邏輯右移16位,與原值進行異或運算(相同為0,不同為1)
對key進行hash函式之後與(size-1)進行相與運算(都為1才為1,其他為0),得到hash槽位
為什麼hash函式如此設計?
hashmap的大小一般小於2^17-1,進行hash槽位計算時只取低16位就夠了,但是這樣子hash衝突的可能性更大,試想一下,低16位相同,而高16位不同這樣的情況很多,把高16參與運算可以有效減少hash衝突
為什麼hashmap的大小建議為2的倍數?
hash槽位計算採用(n - 1) & hash,如果採用2的倍數,那麼槽位就是計算出的hash值的前幾位,比如n為32時,n-1的二進位制為
11111,假設有乙個key的hash值為11001101,那麼槽位就為01101即13;如果不為2的倍數,擴容時自動擴大容量為大於該值最近2的n次方的值
擴容
final node resize()
else if ((newcap = oldcap << 1) < maximum_capacity &&
oldcap >= default_initial_capacity)
//擴容大小為原容量的兩倍
newthr = oldthr << 1; // double threshold
}else if (oldthr > 0)
//第一次put,且設定了初始容量,初始容量為設定的初始容量最接近的大於它的2的n次方值
newcap = oldthr;
else
if (newthr == 0)
threshold = newthr;
@suppresswarnings()
node newtab = (node)new node[newcap];
table = newtab;
//舊容擴新容過程
if (oldtab != null)
else
} while ((e = next) != null);
if (lotail != null)
if (hitail != null) }}
}}
return newtab;
}
resize方法觸發條件1.容量為空,第一次put的時候 2.容量不為空,但超過擴容閾值
設定新容量,新擴容閾值,包含3種情況,map不為空,map為空且設定初始容量,map為空且未設定初始容量
舊容擴新容過程
map putval
final v putval(int hash, k key, v value, boolean onlyifabsent,
boolean evict)
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
//鍊錶中已存在要放入的key值
break;
p = e;}}
if (e != null)
}++modcount;
if (++size > threshold)
//size大於擴容閾值,進行擴容
resize();
afternodeinsertion(evict);
return null;
}
紅黑樹轉化條件為hash槽位鍊錶長度大於8且table.length大於64; JDK原始碼 HashMap 之resize
1.hashmap原始碼閱讀目標 了解具體的資料結構 hash及衝突鍊錶 紅黑樹 和重要方法的具體實現 hashcode equals put resize.2.重要方法 hashcode 與 equals都是在abstractmap中定義的 hashcode是各元素hash的累加 h iter.n...
jdk原始碼解析二之HashMap
hashmap的loadfactor為什麼是0.75?主要涉及到泊松分布的概念,猝 乙個bucket空和非空的概率為0.5,通過牛頓二項式等數學計算,得到這個loadfactor的值為log 2 約等於0.693.同回答者所說,可能小於0.75 大於等於log 2 的factor都能提供更好的效能,...
JDK原始碼學習 HashMap
什麼是hash?hash的意思是 雜湊 音譯做 雜湊 輸入乙個任意長度的資料,進過雜湊運算之後,輸出一段固定長度的資料,作為輸入資料的指紋,輸出的結果就是雜湊值。一般來說輸入資料的空間遠遠大於輸出的雜湊值的空間,輸入不同的資料可能會產生相同的雜湊值,所以很難從雜湊值來逆向推出輸入值是什麼。雜湊函式本...