java hash hashMap詳解

Hash 一般也可叫做散列,你可以把 Hash 簡單的理解爲將一個對象通過 hashCode() 方法映射爲一個 int 類型的值,其中 hashCode() 是定義在 Object 中的,而 java 中所有的類都繼承自 Object。
所以所有的類都有默認的 hashCode() 方法,你可以根據自己的需要去進行重寫。

以你說的 HashMap 爲例:HashMap 在 JDK 默認的實現是 數組+鏈表,也就是一個數組,數組中的每一個元素都是一個鏈表,假設數組爲 array,鏈表爲 list。

HashMap 是對 key 做出了散列處理,也就是求出了 key 所對應的一個 int 值。
比如說你聲明瞭一個HashMap<String, Object> 類型,如果你調用一次 map.put(“key”, object)。
那麼就先調用 “key”.hashCode() 得到一個 int,這個 int 就是 “key” 的哈希值,用得到的這個 int 類型的值餘上 array 的長度,就得到了這個 object 在 array 中的位置。

但是,在實際的使用中,可能會出現一種情況就是兩個不同的對象的哈希值可能是相同的,假設 “key1” 和 “key2” 得到了相同的哈希值,那麼這個時候我們調用 map.put(“key1”, object1) 和 map(“key2”, object2) 他們通過上面的步驟算出來的哈希值是相同的,也就是他們在 array 中的位置是相同的,這個就叫做 散列衝突。

所以這就是爲什麼 JDK 使用 數組+鏈表 的實現形式了。我們通過上面的步驟得到一個對象在 array 中的位置,如果他們的哈希值相同,但是他們不是同一個 String,那麼我們就將後添加的這個 object 添加到 list 中;如果他們是同一個 String,那麼我們就用新的 object 覆蓋它在 list 中的上一個 object。

例如,對於 “key1” 和 “key2” 通過散列得到的在 array 中的位置是相同的,那麼我們判斷 “key1”.equals(“key2”),如果返回 true,我們使用 object2 覆蓋 object1,如果 返回 false,我們將 object2 添加到 list 中。

所以上面調用的結果應該如下,其中 2 是 “key1” 和 “key2” 通過散列的出來的在 array 中的位置:

{
    list0:null,
    list1:null,
    list2:[object1, object2]
}

JDK 使用的這種叫做分離鏈接法,還有一種叫做平方探測發法。有興趣的話可以去看看《數據結構與算法分析》這本書,好像在第 5 章。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章