hashcode

當set集合與map集合中的key是int或String類型時,不用自定義hashCode。當set集合中的元素與map集合中的key是類時,需要自定義hashCode來確保每一個元素不同。

hashCode方法

HashSet和HashMap 使用后臺數(shù)組(backing array)作為桶,并使用鏈表(linked list)存儲鍵/值對。

桶的后臺數(shù)組:如下所示


image.png

1)使用鍵(key)和值(value)將一個對象放入 map 中時,會隱式調(diào)用 hashCode() 方法,返回哈希值(hash code value),比如 123。兩個不同的鍵能夠返回一樣的哈希值。良好的哈希算法(hashing algorithm)能夠?qū)?shù)值分散開。在上面的例子中,我們假設 (“John”,01/01/1956) 的鍵和 (“Peter”, 01/01/1995) 的鍵返回相同的哈希值,都是 123。


image.png

2)當返回一個 hashCode,例如是 123,初始的 HashMap 容量為 10,它如何知道存儲到后臺數(shù)組(backing array)的哪個索引(index)呢?HashMap 內(nèi)部會調(diào)用 hash(int ) 和 indexFor(int h, int length) 方法。這被稱為哈希函數(shù)(hashing function)。
簡要解釋下這個函數(shù):
hashCode() % capacity

123%10=3

456%10=6

這表示,“hashCode = 123”存儲在備份數(shù)組的索引3上。
容量為 10 的情況下,你可能得到的數(shù)字在 0 到 9 之間。
一旦 HashMap 達到容量的 75%,也就是哈希因子(hash factor)默認值 0.75,后臺數(shù)組(backing array)的容量就會加倍,發(fā)生重散列(rehashing)為新的 20 的容量重新分配桶。

hashCode() % capacity

123%20=3

456%20=16

如上圖所示,鍵/值對以鏈表形式存儲。兩個不同的鍵可以產(chǎn)生一樣的 hashCode,例如123,并存儲在同一個 bucket 中,理解這點至關(guān)重要。例如,上面例子中的 “John, 01/01/1956” 和 “Peter, 01/01/1995“ 。你如何只檢索 “John, 01/01/1956” 呢?此時你的 key 所屬類的 equals() 方法會被調(diào)用。它遍歷 bucket 為 “123” 的 LinkedList 中的每個條目,使用 equals() 方法找到并檢索出鍵為 “John, 01/01/1956” 的條目。這就是在你的類中實現(xiàn) hashCode() 和 equals() 方法重要性的原因。如果你使用一個現(xiàn)有的包裝類,如 Integer 或 String 作為鍵,它們已經(jīng)實現(xiàn)了這兩個方法。如果你使用自己寫的類作為鍵,如 “John, 01/01/1956” 這樣含有名字和出生日期屬性的“MyKey”,你有責任正確地實現(xiàn)這些方法。

不同的對象調(diào)用 hashCode() 方法應該返回不同的值。如果不同的對象返回相同的值,會導致更多的鍵/值對存儲在同一個 bucket 中。這會降低 HashMap 和 HashSet 的性能。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容