Wie schreibe ich die Funktion hashCode () für einen zyklischen Graphknoten?

8

Ich habe die folgende Klasse, die als Teil eines Graphen verwendet wird:

%Vor%

Wenn ich Eclipse Source / Generate hashCode() and equals() verwende, erzeugt es diese Methode:

%Vor%

Das Problem ist, dass diese Methode vom aktuellen Objekt auf ihre Kinder und dann während der Berechnung des hashCodes () des ersten untergeordneten Objekts über das parents.hashCode() zurück zum ursprünglichen Knoten geht weiß nicht, dass der hashCode () dort bereits berechnet wurde. Es kommt dann wieder in children des ursprünglichen Knotens und es gibt eine schöne Endlosschleife.

Frage : Wie kann ich überprüfen, dass zwei Instanzen von MyNode das gleiche Objekt sind und gleichzeitig die Endlosschleife vermeiden? Ist es akzeptabel, einen visited boolean in der MyNode-Klasse hinzuzufügen, um die Exploration zu stoppen? Oder gibt es eine bessere Lösung?

Danke!

    
Grégoire C 19.12.2013, 15:54
quelle

3 Antworten

5

Sie sollten keine Kinder oder Eltern von Knoten verwenden, wenn Sie hashCode und equals implementieren. Sie sind veränderbare Eigenschaften. Die Berechnung von hashCode unterscheidet sich nach dem Ändern der Kanten und führt zu fehlerhaften Maps und Set-Sammlungen.

Implementieren Sie hashCode und equals , indem Sie nur unveränderbare Felder verwenden, die einen eindeutigen natürlichen Schlüssel für ein Objekt bilden. Ein Name könnte ein guter Kandidat sein, sofern er nicht geändert werden kann.

Wenn keine unveränderbaren Felder existieren, entweder:

  1. Überschreiben Sie nicht die Methoden hashCode und equals , die Standardeinstellungen sind in Ordnung. Dadurch wird jede Klasseninstanz eindeutig.
  2. Erstellen Sie ein eindeutiges ID-Feld (durch Sequance) und verwenden Sie es als Startwert in hashCode und Vergleich in equals .
Grzegorz Żur 19.12.2013, 16:01
quelle
2

Mit dem Operator == operator können Sie prüfen, ob zwei Objekte dieselbe Instanz sind:

%Vor%

Wenn Sie ein visited -Flag verwenden möchten, sollten Sie es mit einem Lookup (zB Map ) implementieren, da Sie nach dem Ausführen des Codes diese Flags zurücksetzen müssen.

Ich schlage vor, parents / children zu ignorieren und stattdessen jedem Knoten eine eindeutige ID hinzuzufügen.

    
Adam Arold 19.12.2013 16:04
quelle
2

Die einzige Voraussetzung für hashCode() ist, dass zwei Objekte, die gleich sind, denselben Hash-Wert zurückgeben müssen.

Diese Implementierung würde entsprechen:

%Vor%

... weil nichts sagt, dass ungleiche Objekte unterschiedliche Hashcodes haben MÜSSEN.

Natürlich wird hashCode() besser funktionieren, wenn die Werte verteilt werden können. Sie können alles tun, was Sie wollen, solange Sie die Regel über gleiche Objekte nicht brechen. In normalem Allzweckcode, bei dem ich nicht erwarte, dass die Hashes für die Performance kritisch sind, gebe ich im Allgemeinen nur die Hashcodes eines oder mehrerer signifikanter Felder zurück (z. B. Name in diesem Fall), vorausgesetzt, dass diese Felder bei der Berechnung von beteiligt sind Gleichheit, so dass gleiche Objekte den gleichen Hash haben.

Der Punkt ist, dass Sie wirklich equals und hashCode als Paar betrachten müssen, und es ist besser, mit Ihrer Definition von equals zu beginnen.

    
Pete Verdon 19.12.2013 17:10
quelle

Tags und Links