hashCode和equals方法

hashCode和equals方法是Object類中的兩個常用方法。其定義如下:

hashCode()方法有三個關注點:

關注點1:主要是這個hashCode方法對哪些類是有用的,並不是任何情況下都要使用這個方法,(不使用時根本就沒有必要覆寫此方法),而是當涉及到像HashMap、HashSet(他們的內部實現中使用到了hashCode方法)等與hash有關的一些類時,纔會使用到hashCode方法。

關注點2:推薦按照這樣的原則來設計,即 當equals(object)相同時,hashCode()的返回值也要儘量相同,當equals(object)不相同時,hashCode()的返回沒有特別的要求,但是也要儘量不相同以獲取好的性能。

關注點 3:默認的hashCode實現一般是內存地址對應的數字,所以不同的對象,hashCode()的返回值是不一樣的。

在這種缺省實施情況下,只有它們引用真正同一個對象時這兩個引用纔是相等的。同樣,Object提供的hashCode()的缺省實施通過將對象的內存地址對映於一個整數值來生成。

源碼分析

HashMap內部是由Entry<K,V>類型的數組table來存儲數據,其初始狀態如下:

HashMap的存儲結構如下圖所示:

圖中的每一個方格就表示一個Entry<K,V>對象,其中的橫向則構成一個Entry<K,V>[] table數組,而豎向則是由Entry<K,V>的next屬性形成的鏈表。

HashMap在添加元素(put)時的第一步就是計算該元素的key的hash值,用到如下方法:

HashMap對於key的重複性判斷是基於兩個內容的判斷,一個就是hash值是否一樣(會演變成key的hashCode是否一樣),另一個就是equals方法是否一樣(引用一樣則肯定一樣)。e.hash == hash && ((k = e.key) == key || key.equals(k))。

hashCode重寫的原則:當equals方法返回true,則兩個對象的hashCode必須一樣。

equals()方法在get()方法中的使用:

爲什麼要覆寫HashCode()和equals() ?

由於作爲key的對象將通過計算其hashCode來確定與之對應的value的位置,因此任何作爲key的對象都必須實現 hashCode和equals方法。hashCode和equals方法繼承自根類Object,如果你用自定義的類當作key的話,要相當小心,按照散列函數的定義,如果兩個對象相同,即obj1.equals(obj2)=true,則它們的hashCode必須相同,但如果兩個對象不同,則它們的 hashCode不一定不同,如果兩個不同對象的hashCode相同,這種現象稱爲衝突,衝突會導致操作哈希表的時間開銷增大,hashCode()方法目的純粹用於提高效率,所以儘量定義好的 hashCode()方法,能加快哈希表的操作。

如果相同的對象有不同的hashCode,對哈希表的操作會出現意想不到的結果(期待的get方法返回null),要避免這種問題,只需要牢記一條:要同時複寫equals方法和hashCode方法,而不要只寫其中一個。

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