2012-01-31 18 views
5

rozważyć dodanie metody równości do następnej klasy prostych punktach:Jak napisać metodę Równości w Javie

public class Point { 

    private final int x; 
    private final int y; 

    public Point(int x, int y) { 
     this.x = x; 
     this.y = y; 
    } 

    public int getX() { 
     return x; 
    } 

    public int getY() { 
     return y; 
    } 

    // ... 
} 

// moją definicję równych

public boolean equals(Point other) { 
    return (this.getX() == other.getX() && this.getY() == other.getY()); 
} 

Co jest złego w tej metodzie? Na pierwszy rzut oka wydaje się działać OK:

Point p1 = new Point(1, 2); 
Point p2 = new Point(1, 2); 

Point q = new Point(2, 3); 

System.out.println(p1.equals(p2)); // prints true 

System.out.println(p1.equals(q)); // prints false 

Jednak kłopot zaczyna się po uruchomieniu oddanie punktów w kolekcji:

import java.util.HashSet; 

HashSet<Point> coll = new HashSet<Point>(); 
coll.add(p1); 

System.out.println(coll.contains(p2)); // prints false 

Jak to możliwe, że pot nie zawiera p2, choć dodano do niego p1, a p1 i p2 są równymi obiektami?

+0

Dobre wyjaśnienie tutaj: http://bytes.com/topic/java/insights/723476-overriding-equals-hashcode-methods Internalizuj to - jest to jedna z najbardziej podstawowych zasad w Javie i częste pytanie dotyczące wywiadu. –

Odpowiedz

8

Chociaż prawdą jest, że należy wdrożyć hashCode() podczas wdrożenia equals(), że nie jest przyczyną problemu.

To nie jest metoda equals(), której szukasz. Metoda equals musi zawsze mieć następującą sygnaturę: "public boolean equals (Object object)". Oto kod.

public boolean equals(Object object) 
{ 
    if (object == null) 
    { 
    return false; 
    } 

    if (this == object) 
    { 
    return true; 
    } 

    if (object instanceof Point) 
    { 
    Point point = (Point)object; 
    ... now do the comparison. 
    } 
    else 
    { 
    return false; 
    } 
} 

Urządzenie Apache EqualsBuilder class jest przydatne przy implementacji równań.Link jest starszą wersją, ale nadal ma zastosowanie.

Jeśli podobał Ci się Apache EqualsBuilder, prawdopodobnie spodoba Ci się również Apache HashCodeBuilder class.

Edytuj: zaktualizowano przykład metody równomiernej dla standardowych skrótów.

+1

Rewizja dla jedynego postu, aby to wskazać. –

+0

@Louis: Prawie jedyny ... :-) – Dirk

+0

No cóż. Jedyny jak na mój komentarz, który widziałem. –

4

Musisz wdrożyć hashCode(), gdy zastąpisz equals(). Ci dwaj współpracują ze sobą i muszą przez cały czas zapewniać spójne wyniki. Nieprzestrzeganie tego spowoduje tylko błędne zachowanie, które zaobserwowałeś.

Zostało to wyjaśnione bardziej szczegółowo, np. w pozycji Effective Java 2nd Edition, pozycja 9: Zawsze zastępuj hashCode, gdy zastąpisz wartość równą.

0

Kiedy przesłanianie equals, trzeba też zastąpić hashCode (w szczególności, jeśli masz zamiar używać HashSet lub HashMap ...). Odpowiedni (choć nie mądry) realizacja będzie:

int hashCode() { 
    return x * 31 + y; 
} 

Kolejnym punktem (gra słów nie przeznaczonych): Nie są faktycznie przesłanianie metody equals(Object) zdefiniowaną w klasie Object, ale zamiast definiowania nowego. Prawidłowy sposób byłoby:

boolean equals(Object other) { 
    if (other == this) return true; 
    else if (!(other instanceof Point)) return false; 
    else { 
     Point p = (Point)other; 
     return x == p.getX() && y == p.getY(); 
    } 
} 

Uwaga, że ​​metoda equals ma pretty strong contract z nim związane, które jesteś do spełnienia.

1

Zgodnie z umową pod numerem equals() należy również wprowadzić hashCode().

Z JavaDoc na equals(): Uwaga

że zasadniczo należy zastąpić metodę hashCode zawsze, gdy metoda ta nie jest uwzględniana, tak aby zachować ogólną umowę metody hashcode, który stanowi, że równość obiekty musi mieć równe kody skrótu.

1

Oprócz innych odpowiedzi:

Jeśli używasz Eclipse jako IDE, można po prostu użyć „Źródło” -> „Generuj hashCode() i equals(), aby uzyskać podstawowe wdrożenie robić. .! że to, co kiedykolwiek chcesz

2

działa dobrze nadrzędnymi hashcode

zawsze pamiętać. przesłanianie hashCode gdy zastępują równych

@Override public int hashCode() { 
     return (41 * (41 + getX()) + getY()); 
    } 

To są moje implementacje hashCode.

+0

To nie generuje unikalnego skrótu ... 2 proste przykłady 'x = 1',' y = 0', 'Hash = 1722' OR' x = 0', 'y = 41',' Hash = 1722' – Basic

Powiązane problemy