2012-06-11 46 views
2

,作爲人的定義:如何覆蓋這個hashCode方法?

public class Person { 
    private int id; 
    private int characteristics; 
    public boolean equals (Object obj) { 
      if (obj == this) { 
       return true; 
      } 
      if (obj instanceof Person) { 
       if (id == ((Person) obj).id) { 
        return true; 
       } else if (characteristics == ((Person) obj).characteristics) { 
        return true; 
       } 
      } 
      return false; 
    } 
} 

原因2個Person對象ab必須有相同的哈希碼,如果a.equals(b)回報true,應該怎麼實現hashCode方法?

解決方案

equals方法實現,根據Java的等效協議是不正確的:傳遞不滿意:a.id = 1a.characteristic = 2b.id = 1b.characteristic = 3c.id = 2c.characteristic = 3; a.equals(b) == trueb.equals(c) == true,但是a.equals(c) == false

+1

您可以異或ID和特徵變量。 –

+0

爲了記錄,您可以將第二組這些「if」轉換爲回報,即。 'return obj instanceof Person &&(id ==((Person)obj).id || characteristics ==((Person)obj).characteristics);'。你還應該在當前代碼的末尾註意'return false',因爲你的'equals'方法可能不會返回任何東西。 – SimplyPanda

+3

@SimplyPanda第一個是完全錯誤的。 'return obj == this;'如果'obj'不是相同的實例,將會返回false,但是可能仍然是相等的值。 – cdhowie

回答

5

由於類認爲當任其各自idcharacteristics字段都是相等的對象相等,則可以合理利用這裏唯一的哈希碼是所有的恆定值實例:

public int hashCode() { 
    return 0; 
} 

這將使基於散列的查找性能非常糟糕。

equals()中的任一個或者測試通常是一個壞主意;對象實際上不是等於,是嗎?也許他們只是一個「匹配對方?」也許你應該考慮單獨離開equals()並執行一些其他比較方法。


由於Thomasz指出的那樣,你equals()測試不傳遞;如果a.equals(b) && b.equals(c)爲真,則a.equals(c)必須爲真。這是而不是與您的超負荷一致,因此您的實施違反equals()的合同。我強烈建議您以不同的方法實施此測試,並且只保留equals()

+2

這是正確的答案:)(等於set/collections是好的,只是hashcode在OP的情況下不起作用) – bestsss

1

這是你的類什麼自動生成:

@Override 
public int hashCode() { 
    int result = id; 
    result = 31 * result + characteristics; 
    return result; 
} 

而經過幾年的重構:

@Override 
public int hashCode() { 
    return 31 * id + characteristics; 
} 

並記錄在案,只是我還是你的equals()壞了?如果id s或characteristics相等,但不一定是兩者,則認爲兩個對象相等。這意味着你的平等不是傳遞一旦你的對象進入荒野,這可能會有真正意想不到的副作用。

這裏是一個體面的實現:

@Override 
public boolean equals(Object o) { 
    if (this == o) { 
     return true; 
    } 
    if (!(o instanceof Person)) { 
     return false; 
    } 

    Person person = (Person) o; 
    return characteristics == person.characteristics && id == person.id; 
} 
+1

這似乎不是完全對我來說,不是OP的equals()方法指示if(id == person.id)|| (特徵== person.characteristics) – NominSim

+0

YES:'if(id == person.id)|| (特徵== person.characteristics)' –

+0

@NominSim:你是對的。然而,由OP定義的'equals()'不是可傳遞的,我的'hashCode()'對正確的'equals()'有效 - 我後來才注意到。我接受你謙虛的downvote,但我相信OP有更大的問題,然後... –

0

如果具有相同id意味着始終具有相同characteristics(您equals()是有效的,這似乎有必要),那麼你的哈希代碼可以使用characteristics獨自:

@Override 
public int hashCode() { 
    return characteristics; 
} 

如果不是的話,你@cdhowie建議,可能要重新考慮使用Java平等來表達這種關係。