爲什麼在重寫了equals()方法之後也必須重寫hashCode()方法

我們都知道Java語言是完全面向對象的,在java中,所有的對象都是繼承於Object類。Object類中有兩個方法equals、hashCode,這兩個方法都是用來比較兩個對象是否相等的。
在沒有重寫equals方法的時候我們是繼承了Object的equals方法,該方法是用來比較兩個對象的內存地址,顯然我們new了兩個對象內存地址肯定不一樣。

  • 對於值對象,==比較的是兩個對象的值
  • 對於引用對象,比較的是兩個對象的地址

默認的equals方法同==,一般來說我們的對象都是引用對象,要重寫equals方法。
現在有一個學生對象,有屬性學號跟姓名,現在我新建一個學生對象,又從數據裏查出一個學生對象,這兩個對象的學號跟姓名一樣,那這兩個對象是不是相等呢?一般情況下,除非你有特殊需求要處理,這兩個對象是相等的,可如果用==去比較,返回的結果卻是false。
這時候我們就必須重寫equals方法了。如果學號是主鍵,在equals方法裏,我們認識只要學號相同,就可以返回true。
hashCode方法也是可以用來比較兩個對象是否相等的。但是我們很少使用,應該說是很少直接使用。hashCode方法返回的是一個int值,可以看做是一個對象的唯一編碼,如果兩個對象的hashCode值相同,我們應該認爲這兩個對象是同一個對象。

一般如果使用java中的Map對象進行存儲時,他會自動調用hashCode方法來比較兩個對象是否相等。
所以如果我們對equals方法進行了重寫,建議一定要對hashCode方法重寫,以保證相同的對象返回相同的hash值,不同的對象返回不同的hash值。
如上面的學生例子,如果學號相同,不管姓名不相同,返回的hash值一定要是一樣的,這時我們的hash值只與學號有關。

public class Test {    
     public static void main(String[] args) {    
     HashMap hm = new HashMap();    
     hm.put(new key(1),new value(2));    
     if(hm.containsKey(new key(1)))    
      System.out.println(hm.get(new key(1)));    
     else    
      System.out.println("dont have such a key");    
     }   
}    

你每次new一個新對象出來hashCode值肯定不一樣,所以你拿不到你要的key。

class key {    
   int i ;    
   public key(int i) {    
        this.i = i;    
   }    

   public boolean equals(Object obj) {    
        if(obj instanceof key) {    
                if(((key)obj).i == i)    
                    return true;    
        }    
        return false;    
   }    

   public int hashCode() {    
        return i;    
   }    
}  
  1. 重寫equals方法時需要重寫hashCode方法,主要針對Map、Set等集合類型的使用。
    a: Map、Set等集合類型存放的對象必須是唯一的;
    b: 集合類型判斷兩個對象是否相等,是先判斷equals是否相等,如果equals返回true,還要再判斷hashCode返回值是否true,只有兩者都返回true,才認爲該兩個對象是相等的。
  2. 由於Object的hashCode返回是對象的hash值,所以即使equals返回true,集合也可能判定兩個對象不等,所以必須重寫hashCode方法,以保證當equals返回true時,hashCode也返回true,這樣才能使得集合中存放的對象唯一。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章