為什么要重寫hashCode()和equals()方法


1、剖析 equals()

//Object類中的equals()
public boolean equals(Object obj) {     
    return (this == obj);     
    } 

 equals()的定義為:

public native int hashCode();

是一個本地方法,返回的對象的地址值。

內部是使用“==”比較引用是否指向同一個對象。所以在不覆蓋equals方法時,使用equals方法和==的比較結果是一樣的


2、什么時候應該覆蓋equals方法呢?

當我們希望知道它們在邏輯上是否相等,而不是想知道它們是否指向同一個對象時,我們便需要覆蓋equals方法了。

覆蓋equals方法的通用約定:

1、自反性  對於任何非null的引用值,x.equals(x) == true

2、對稱性 對於任何非null的引用值x,y,x.equals(y) == y.equals(x)

3、傳遞性  對於任何非null的引用值x,y,z,x.equals(y) ==true,y.equals(z)==true,------>x.equals(z)==true

4、一致性 對於任何非null的引用值x,y,只要equals的比較操作在對象中所用的信息沒有被改變,多次調用x.equals(y)返回的值不變。

5、對於任何非null的引用值x,x.equals(null)必須返回false。

實現equals()方法的小技巧:

1,使用==操作符檢查 參數是否為這個對象的引用,是則直接返回true。

2,使用instance操作符檢查 參數是否為正確的類型。

3,把參數轉換成正確的類型。

4,對於該類中的每個關鍵域,檢查參數中的域是否與該對象對應的域匹配。先比較最有可能不一致的域。

5,覆蓋equals方法時總要覆蓋hashCode方法。

6,不要將equals聲明中的Object對象替換為其他對象。

3、為什么覆蓋equals方法時總要覆蓋hashCode方法?

因為如果不這么做的話,就違反了Object.hashCode的通用約定,導致該類無法結合所有基於散列的集合(HashMap,HashSet,HashTable)一起正常運作.

在應用程序執行期間,只要equals方法的比較操作用到的信息沒變,那么對這同一個對象調用多次,hashCode方法都必須始終如一的返回同一個整數.但在應用程序的多次執行中,即重新啟動后結果可以不一致.
如果兩個對象根據equals比較是相等的,那這兩個對象調用hashCode方法返回的結果必須是一樣的.
如果兩個對象根據equals比較是不相等,那這兩個對象調用hashCode方法返回的結果不一定不同.但不同的對象產生不同的hasCode,可以提高散列表的性能.
不覆蓋hashCode而違反的關鍵約定是第二條:相等的對象必須具有相等的hashCode.
如果相同的對象具有不同的hashCode,那么將對象放入hashMap中,對象會被存放到不同的桶中,當去get 時,雖然是同一個對象,但是由於生成的hashCode不同,會到不同的桶中去找,此時便找不到那個對象

  4.hashcode()和equals()是在哪里被用到的?什么用的?

     HashMap是基於散列函數,以數組和鏈表的方式實現的。
而對於每一個對象,通過其hashCode()方法可為其生成一個整形值(散列碼),該整型值被處理后,將會作為數組下標,存放該對象所對應的Entry(存放該對象及其對應值)。

 

 equals()方法則是在HashMap中插入值或查詢時會使用到。當HashMap中插入 值或查詢值對應的散列碼與數組中的散列碼相等時,則會通過equals方法比較key值是否相等,所以想以自建對象作為HashMap的key,必須重寫 該對象繼承object的equals方法。

    
 5.本來不就有hashcode()和equals()了么?干嘛要重寫,直接用原來的不行么?
     

      HashMap中,如果要比較key是否相等,要同時使用這兩個函數!因為自定義的類的hashcode()方法繼承於Object類,其hashcode碼為默認的內存地 址,這樣即便有相同含義的兩個對象,比較也是不相等的,例如,

 

Student st1 = new Student("wei","man");

 

Student st2 = new Student("wei","man"); 

 

正常理解這兩個對象再存入到hashMap中應該是相等的,但如果你不重寫 hashcode()方法的話,比較是其地址,不相等!

      HashMap中的比較key是這樣的,先求出key的hashcode(),比較其值是否相等,若相等再比較equals(),若相等則認為他們是相等 的。若equals()不相等則認為他們不相等。如果只重寫hashcode()不重寫equals()方法,當比較equals()時只是看他們是否為 同一對象(即進行內存地址的比較),所以必定要兩個方法一起重寫。HashMap用來判斷key是否相等的方法,其實是調用了HashSet判斷加入元素 是否相等。

由於在項目里經常會用到HashMap,所以在面試的時候基本會問這個問題。

你有沒有重寫過hashCode方法?

你在使用HashMap時有沒有重寫hashCode和equals方法?你是怎么寫的?

一個對象的hashcode可以改變么?

如果大家要在HashMap的“鍵”部分存放自定義的對象,一定要在這個對象里用自己的equals和hashCode方法來覆蓋Object里的同名方法。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM