爲何覆寫equals必需要覆寫hashCode? 爲何覆寫equals必需要覆寫hashCode?

=============================================html

原文連接: 爲何覆寫equals必需要覆寫hashCode? 轉載請註明出處!java

=============================================api

《Effective java》Chapter Three  Item 9:Always override hashCode when you overried equals. (下載連接: Effective_java(英文版)第二版.pdf oracle

 一、 在Object中有兩個方法:app

public native int hashCode(); 
public boolean equals(Object obj) {
  return (this == obj);//默認比較引用相等
}

 因此任何一個對象都有默認的hashCode()和equals()方法。ide

 二、在hash表中,hashCode()方法是參與取/存值運算的。post

     例如: ui

//HashTabel
if ((e.hash == hash) && e.key.equals(key)) {
     return (V)e.value;
}
//HashMap
 if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k))))
     return e;

    因而可知,在根據key取value的時候,key相等的必要條件就是二者hashCode相等。this

    再說爲何覆寫equals必需要覆寫hashCode?注意:研究的對象是同一個類的兩個不一樣對象(引用不一樣)url

   先看一段代碼:

    @Test
    public void testHashCode(){
        Student stu1 = new Student("JACK");
        Student stu2 = new Student("JACK");
        System.out.println(stu1.equals(stu2));//equal返回true
        System.out.println(stu1.hashCode()+"----"+stu2.hashCode());//hashCode 結果不一樣。因爲Student未覆寫hashCode方法,在計算的時候使用的是的Object.hashCode(),計算出來二者的hashCode不一致
        HashMap map = new HashMap();
        map.put(stu1,"123456");
        System.out.println(map.get(stu2));//(邏輯上)本想取出「123456」,但hashMap在取值的時候把二者的hashCode加入比較,所以找不到相等的key值,因此取出結果爲null
        
    }
    class Student {
        private String name;
        public Student(String name){
            this.name = name;
        }
        @Override
        public boolean equals(Object obj) {
            //邏輯上名字相等便認爲二者相等並非把引用相等做爲判等條件
            return this.name.equals(((Student)obj).name);
        }
    }

 

 運行結果以下:

true
668849042----434176574
null

 

 由這段代碼能夠看出:在執行map.get(stu2)的時候,程序會獲取stu2的hashCode。而Student未覆寫hashCode(),因此直接使用父類Object.hashCode()計算hash值,而因爲Object.hashCode()返回的stu1和stu2的hash值並不相同,所以,map中未找到stu2對應的key值,因此返回的value便爲null。

而示例程序中,本想根據名字相等來判斷對象相等獲取value值「123456」,可因爲調用hashCode()的返回值不一樣致使最終未取得想要的值。那麼解決辦法是什麼?讓stu1.hashCode() == stu2.hashCode()。那麼該如何實現? 自定義(覆寫)hashCode()方法。

 因此若是自定義了equals()方法,且返回true的充要條件不是(this == obj),那麼就必須覆寫hashCode,且必須保證equals爲true的時候二者的hashCode必須相等,不然當該對象做爲key值存在hash表中的時候,就沒法用邏輯上相等的對象取出該key所對應的value(如示例)。

Object specification:

Object specification [JavaSE6]:
• Whenever it is invoked on the same object more than once during an execution of an application, the hashCode method must consistently return the same integer, provided no information 
  used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application. • If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result. • It is not required that
if two objects are unequal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results.
  However, the programmer should be aware that producing distinct integer results
for unequal objects may improve the performance of hash tables.

 

----end

相關文章
相關標籤/搜索