hashmap源碼解析,JDK1.8和1.7的區別

背景:hashmap面試基礎必考內容,須要深刻了解,並學習其中的相關原理。此處還要明白1.7和1.8不通版本的優化點。html

Java 8系列之從新認識HashMap

Java 8系列之從新認識HashMapjava

鑑於JDK1.8作了多方面的優化,整體性能優於JDK1.7,下面咱們從兩個方面用例子證實這一點(在hash均勻和不均勻的狀況下性能都有明顯的提高)面試

無論增長、刪除、查找鍵值對,定位到哈希桶數組的位置都是很關鍵的第一步。前面說過HashMap的數據結構是數組和鏈表的結合,因此咱們固然但願這個HashMap裏面的元素位置儘可能分佈均勻些,儘可能使得每一個位置上的元素數量只有一個,那麼當咱們用hash算法求得這個位置的時候,立刻就能夠知道對應位置的元素就是咱們要的,不用遍歷鏈表,大大優化了查詢的效率。HashMap定位數組索引位置,直接決定了hash方法的離散性能。先看看源碼的實現(方法一+方法二):算法

方法一:
static final int hash(Object key) {   //jdk1.8 & jdk1.7
     int h;
     // h = key.hashCode() 爲第一步 取hashCode值
     // h ^ (h >>> 16)  爲第二步 高位參與運算
     return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
方法二:
static int indexFor(int h, int length) {  //jdk1.7的源碼,jdk1.8沒有這個方法,可是實現原理同樣的
     return h & (length-1);  //第三步 取模運算
}

這裏的Hash算法本質上就是三步:取key的hashCode值、高位運算、取模運算。數組

對於任意給定的對象,只要它的hashCode()返回值相同,那麼程序調用方法一所計算獲得的Hash碼值老是相同的。咱們首先想到的就是把hash值對數組長度取模運算,這樣一來,元素的分佈相對來講是比較均勻的。可是,模運算的消耗仍是比較大的,在HashMap中是這樣作的:調用方法二來計算該對象應該保存在table數組的哪一個索引處。安全

這個方法很是巧妙,它經過h & (table.length -1)來獲得該對象的保存位,而HashMap底層數組的長度老是2的n次方,這是HashMap在速度上的優化。當length老是2的n次方時,h& (length-1)運算等價於對length取模,也就是h%length,可是&比%具備更高的效率。數據結構

在JDK1.8的實現中,優化了高位運算的算法,經過hashCode()的高16位異或低16位實現的:(h = k.hashCode()) ^ (h >>> 16),主要是從速度、功效、質量來考慮的,這麼作能夠在數組table的length比較小的時候,也能保證考慮到高低Bit都參與到Hash的計算中,同時不會有太大的開銷。多線程

Java源碼分析:HashMap 1.8 相對於1.7 到底更新了什麼?

Java源碼分析:HashMap 1.8 相對於1.7 到底更新了什麼?源碼分析

ps超詳細的 太牛逼了 好好讀讀post

1.8不會出現1.7的多線程環形鏈死循環狀況,可是還不是線程安全的,由於沒有同步鎖。

jdk1.8與1.7之間 hashmap的不一樣,優化點!!

全部處理的根本目的,都是爲了提升 存儲key-value的數組下標位置 的隨機性 & 分佈均勻性,儘可能避免出現hash值衝突。即:對於不一樣key,存儲的數組下標位置要儘量不同

JDK 1.8 的優化目的主要是:減小 Hash衝突 & 提升哈希表的存、取效率

相關文章
相關標籤/搜索