淺談HashMap
談論這個問題,需要用jdk1.7和jdk1.8對比來看,來說,不然面試官會覺得你是個low貨,他本身期待你自己說的時候,對比來說。具體從這幾個方面對比來說:結構,原理,插入鍵值對的put方法的區別,擴容策略,擴容檢查順序,流程圖。
結構:
1.7版本:陣列+單向連結串列(HashMap底層就是一個數組,陣列中的每一項又是一個單向連結串列)
1.8版本:陣列+hash表+紅黑樹
底層原理(這裡不區分版本,回答下面這段即可):
我們通過put()和get()方法儲存和獲取物件。當我們將鍵值對傳遞給put()方法時,它呼叫鍵物件的hashCode()方法來計算hashcode,讓後找到bucket位置來儲存值物件。當獲取物件時,通過鍵物件的equals()方法 找到正確的鍵值對,然後返回值物件。HashMap使用連結串列來解決碰撞問題,當發生碰撞了,物件將會儲存在連結串列的下一個節點中。 HashMap在每個連結串列節點中儲存鍵值對物件。
插入鍵值對的put方法的區別:
1.7版本:1.7中是採用頭插;
1.8版本:1.8中會將節點插入到連結串列尾部(因為JDK1.7是用單鏈表進行的縱向延伸,當採用頭插法時會容易出現逆序且環形連結串列死迴圈問題。但是在JDK1.8之後是因為加入了紅黑樹使用尾插法,能夠避免出現逆序且連結串列死迴圈的問題。)
擴容策略:
1.7版本:1.7中是隻要不小於閾值就直接擴容2倍;
1.8版本:1.8的擴容策略會更優化,當陣列容量未達到64時,以2倍進行擴容,超過64之後若桶中元素個數不小於7就將連結串列轉換為紅黑樹,但如果紅黑樹中的元素個數小於6就會還原為連結串列,當紅黑樹中元素不小於32的時候才會再次擴容
擴容檢查順序:
1.7版本:是先進行擴容後進行插入的。
1.8版本:JDK1.8的時候則是先插入後進行擴容的。
流程圖(口語化能夠說出流程):
1.8版本:
1.7版本:
1.8版本: