2016-12-04 2 views
2
class Node{ 
    int x, y, value; 
    Node(int x, int y, int v) { 
     this.x = x; 
     this.y = y; 
     value = v; 
    } 

    @Override 
    public boolean equals(Object o) { 
     Node n = (Node)o; 
     boolean result = this.x == n.x && this.y == n.y && this.value == n.value; 
     return result; 
    } 
} 

void test() { 
    HashSet<Node> s = new HashSet<>(); 
    Node n2 = new Node(1, 1, 11); 
    Node n1 = new Node(1, 1, 11); 
    s.add(n1); 
    System.out.println(s.contains(n2)); 
    System.out.println(n1.equals(n2)); 
} 

kehrt:HashSet sagt es kein Element enthält, obwohl gleich true zurück

falsch

wahr

Per https://docs.oracle.com/javase/8/docs/api/java/util/HashSet.html#contains-java.lang.Object- verwendet HashSet gleich zu beurteilen, ob es enthält ein Element. Sollte der contains call also hier nicht wahr sein? Was vermisse ich? Vielen Dank.

+3

Sie müssen 'hashCode()' auch überschreiben. – Eran

Antwort

3

Siehe javadoc für Object.equals():

Beachten Sie, dass es in der Regel notwendig ist, die Methode hashCode, wenn diese Methode überschrieben außer Kraft zu setzen, um den allgemeinen Auftrag für die hashCode-Methode, die das muss gleich Objekte Staaten zu erhalten haben gleiche Hash-Codes.

Das fehlt in Ihrer Klasse! Diese here kann Ihnen einige Ideen wie hashCode() Ihre Klasse geben.

3

Das erste, was mir in den Sinn kommt, ist, dass Sie auf eine unangemessene Weise gleichrangig sind. Sie überlegen nicht, Referenz, Null-Objekt oder Klasse selbst zu vergleichen.

so etwas wie dies in Ihrer Methode equals fehlt:

if (this == obj) 
    return true; 
if (obj == null) 
    return false; 
if (getClass() != obj.getClass()) 
    return false; 

Auf der anderen Seite, haben Sie für die Node-Klasse richtig, den Vertrag zu implementieren: dh Sie außer Kraft setzen müssen, ist gleich UND hashCode zu

0

Ich werde Ihnen erklären, warum hashcode() außer Kraft setzen, dafür müssen Sie im Grunde verstehen, wie HashSet funktioniert.

Die erste Sache ist, weil Sie nicht überschreiben hashcode(), Ihre Node Klasse wird die Standard-Implementierung von java.lang.Object Klasse erhalten.

Sie können eine System.out.println hinzufügen und die Hashcodes von beiden der Node Objekte in Ihrem equals() drucken, wie unten dargestellt:

@Override 
public boolean equals(Object o) { 
    Node n = (Node)o; 
    //Add System.out.println to check the hashcodes 
    System.out.println(n.hashCode()+"::::::"+this.hashCode()); 

    boolean result = this.x == n.x && this.y == n.y && this.value == n.value; 
    return result; 
} 

Sie können die Ausgabe überprüfen, indem Sie das obige Verfahren ausgeführt wird, werden Sie, dass sehen die Hashcodes sind für beide Objekte unterschiedlich, dh es wurde bewiesen, dass die beiden Objekte gleich sind, aber ihre Hashcodes unterschiedlich sind.

kommt nun zum hashSet.contains(n2), wie HashSet Arbeiten ist, dass es die Objekte in verschiedene Eimer speichert auf ihre Hashcodes basiert. So Ihre zwei Node Objekte fallen unter zwei verschiedene Eimer und wird false zurückgeben.

also zusammenfassen, die Regel ist, dass die gleichen Objekte gleich Hash-Codes haben müssen, so dass Sie immer hashcode() außer Kraft setzen müssen zusammen mit Ihren equals() so, dass Sie nicht den widersprüchlichen Ergebnissen wie die oben equals() erhalten und

Verwandte Themen