1. 程式人生 > 實用技巧 >重新equals和hashcode

重新equals和hashcode

1.equals()方法和hashCode()方法是什麼?

  1. equals()和hashCode()都是是Java中萬物之源Object類中的方法;
  2. equals方法用於比較兩個物件是否相同,Object類中equals方法的實現是比較引用地址來判斷的物件是否是同一個物件,通過覆蓋該方法可以實現自定義的判斷規則;
  3. hashCode是jdk根據物件的地址或者字串或者數字計算該物件的雜湊碼值的方法。

2.為什麼要重寫equals()方法?

  1. Object類中equals方法比較的是兩個物件的引用地址,只有物件的引用地址指向同一個地址時,才認為這兩個地址是相等的,否則這兩個物件就不想等。
  2. 如果有兩個物件,他們的屬性是相同的,但是地址不同,這樣使用equals()比較得出的結果是不相等的,而我們需要的是這兩個物件相等,因此預設的equals()方法是不符合我們的要求的,這個時候我們就需要對equals()方法進行重寫以滿足我們的預期結果。
  3. 在java的集合框架中需要用到equals()方法進行查詢物件,如果集合中存放的是自定義型別,並且沒有重寫equals()方法,則會呼叫Object父類中的equals()方法按照地址比較,往往會出現錯誤的結果,此時我們應該根據業務需求重寫equals()方法。

3.為什麼要重寫hashCode()方法?

  1. hashCode()方法用於雜湊資料的快速儲存,HashSet/HashMap/Hashtable類儲存資料時都是根據儲存物件的hashcode值來進行分類儲存的,一般先根據hashcode值在集合中進行分類,在根據equals()方法判斷物件是否相同。
  2. HashMap物件是根據其Key的hashCode來獲取對應的Value。
  3. 生成一個好的hashCode值能提高HashSet查詢的效能,差的hashCode值不但不能提高效能,甚至可能造成錯誤。比如hashCode方法中返回常量,會讓,HashSet的查詢效率退化為List集合的查詢效率;hashCode方法中返回隨機數,會讓查詢結果變的不可預測。
  4. 好的hashCode生成方式是讓物件中的關鍵屬性與質數相乘,並將積相加獲取。

4.為什麼java中在重寫equals()方法後必須對hashCode()方法進行重寫?

  1. 為了維護hashCode()方法的equals協定,該協定指出:如果根據 equals()方法,兩個物件是相等的,那麼對這兩個物件中的每個物件呼叫 hashCode方法都必須生成相同的整數結果;而兩個hashCode()返回的結果相等,兩個物件的equals()方法不一定相等。
  2. HashMap物件是根據其Key的hashCode來獲取對應的Value。
  3. 在重寫父類的equals()方法時,也重寫hashcode()方法,使相等的兩個物件獲取的HashCode值也相等,這樣當此物件做Map類中的Key時,兩個equals為true的物件其獲取的value都是同一個,比較符合實際。

5.重寫equals()方法:

重寫equals方法需要遵循Java如下規則,否則編碼行為會難以揣測:

  1. 自反性:對於任意的物件x,x.equals(x)返回true(自己一定等於自己);
  2. 對稱性:對於任意的物件x和y,若x.equals(y)為true,則y.equals(x)亦為true;
  3. 傳遞性:對於任意的物件x、y和z,若x.equals(y)為true且y.equals(z)也為true,則x.equals(z)亦為true;
  4. 一致性:對於任意的物件x和y,x.equals(y)的第一次呼叫為true,那麼x.equals(y)的第二次、第三次、第n次呼叫也均為true,前提條件是沒有修改x也沒有修改y;
  5. 對於非空引用x,x.equals(null)永遠返回為false。

重寫程式碼如下:


    @Override
    public boolean equals(Object o) {
        //自反性
        if (this == o) return true;
        //任何物件不等於null,比較是否為同一型別
        if (!(o instanceof Person)) return false;
        //強制型別轉換
        Person person = (Person) o;
        //比較屬性值
        return getId() == person.getId() &&
                Objects.equals(getName(), person.getName()) &&
                Objects.equals(getSex(), person.getSex());
    }

6.重寫hashCode()方法:

HashMap物件是根據其Key的hashCode來獲取對應的Value。
在重寫父類的equals方法時,也重寫hashcode方法,使相等的兩個物件獲取的HashCode也相等,這樣當此物件做Map類中的Key時,兩個equals為true的物件其獲取的value都是同一個,比較符合實際。

重寫hashCode()方法需要遵循hashCode()協定:

    1. 一致性:在Java應用程式執行期間,在對同一物件多次呼叫hashCode方法時,必須一致地返回相同的整數,前提是將物件進行hashcode比較時所用的資訊沒有被修改。
    2. equals:如果根據equals()方法比較,兩個物件是相等的,那麼對這兩個物件中的每個物件呼叫hashCode()方法都必須生成相同的整數結果,注:這裡說的equals()方法是指Object類中未被子類重寫過的equals()方法。
    3. 附加:如果根據equals()方法比較,兩個物件不相等,那麼對這兩個物件中的任一物件上呼叫hashCode方法不一定生成不同的整數結果。但是,程式設計師應該意識到,為不相等的物件生成不同整數結果可以提高雜湊表的效能。