Treeset.contains () Problem

7

Ich habe also schon seit einiger Zeit mit einem Problem zu kämpfen, dachte, ich könnte hier genauso gut um Hilfe bitten.

Ich füge Ticketobjekte zu einem TreeSet hinzu, Ticket implementiert Comparable und hat die Methoden equals (), hashCode () und CompareTo () überschrieben. Ich muss überprüfen, ob ein Objekt bereits im TreeSet ist, indem ich contains () verwende. Jetzt nach dem Hinzufügen von 2 Elementen zum Set ist alles in Ordnung, aber nach dem Hinzufügen eines dritten wird es vermasselt.

Nach dem Hinzufügen eines dritten Elements zum TreeSet wird dieses kleine Stück Code ausgeführt. Ticket temp2 ist das Objekt, nach dem ich suche (verkoopLijst).

%Vor%

gibt das zurück:

%Vor%

Nun wäre meine Frage, wie das überhaupt möglich ist?

Bearbeiten:

%Vor%     
Jasper 08.08.2010, 01:45
quelle

3 Antworten

16

Am compareTo Vertrag

Das Problem liegt in Ihrem compareTo . Hier ein Auszug aus der Dokumentation :

  

Der Implementierer muss sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) für alle x und y sicherstellen.

Ihr ursprünglicher Code wird hier als Referenz reproduziert:

%Vor%

Warum ist der return 1; ein Fehler? Stellen Sie sich das folgende Szenario vor:

  • Gegeben Ticket t1, t2
  • Gegeben t1.boeking.compareTo(t2.boeking) == 0
  • Gegeben t1.equals(t2) return false
  • Jetzt haben wir beide der folgenden:
    • t1.compareTo(t2) gibt 1 zurück
    • t2.compareTo(t1) gibt 1 zurück

Diese letzte Konsequenz ist eine Verletzung des compareTo Vertrags.

Problem beheben

In erster Linie sollten Sie die Tatsache ausgenutzt haben, dass Comparable<T> ein parametrisierbarer generischer Typ ist. Das heißt statt:

%Vor%

es wäre viel angemessener, stattdessen etwas wie das zu deklarieren:

%Vor%

Jetzt können wir unsere compareTo(Ticket) (nicht mehr compareTo(Object) ) schreiben. Es gibt viele Möglichkeiten, dies umzuschreiben, aber hier ist eine ziemlich einfache, die funktioniert:

%Vor%

Nun können wir auch equals(Object) in compareTo(Ticket) definieren anstatt umgekehrt:

%Vor%

Beachten Sie die Struktur von compareTo : Sie enthält mehrere return -Anweisungen, aber der Fluss der Logik ist tatsächlich gut lesbar. Beachten Sie auch, dass die Priorität der Sortierkriterien explizit und leicht umsortierbar ist, wenn Sie unterschiedliche Prioritäten berücksichtigen.

Verwandte Fragen

polygenelubricants 08.08.2010, 08:02
quelle
4

Dies kann passieren, wenn Ihre compareTo-Methode nicht konsistent ist. I.e. Wenn a.compareTo(b) > 0 , dann muss b.compareTo(a) & lt sein; 0. Und wenn a.compareTo(b) > 0 und b.compareTo(c) > 0 , dann muss a.compareTo(c) & gt; 0. Wenn das nicht wahr ist, kann TreeSet alles durcheinander bringen.

    
Paul Tomblin 08.08.2010 02:00
quelle
3

Erstens: Wenn Sie TreeSet verwenden, wirkt sich das tatsächliche Verhalten Ihrer hashCode -Methoden nicht auf die Ergebnisse aus. TreeSet ist nicht auf Hashing angewiesen.

Wirklich müssen wir mehr Code sehen; z.B. die tatsächlichen Implementierungen der Methoden equals und compareTo und der Code, der TreeSet instanziiert.

Wenn ich jedoch raten sollte, wäre es überladen die Methode equals , indem Sie sie mit der Signatur boolean equals(Ticket other) deklarieren. Das würde zu dem Verhalten führen, das Sie sehen. Um das erforderliche Verhalten zu erhalten, müssen Sie die Methode überschreiben ; z.B.

%Vor%

(Es ist eine gute Idee, die Annotation @Override einzufügen, um deutlich zu machen, dass die Methode eine Methode in der Oberklasse überschreibt oder eine Methode in einer Schnittstelle implementiert. Wenn Ihre Methode keine Überschreibung ist, dann Sie werden einen Kompilierungsfehler bekommen ... was eine gute Sache wäre.)

BEARBEITEN

Basierend auf dem Code, den Sie der Frage hinzugefügt haben, besteht das Problem nicht in Overload und Override. (Wie gesagt, ich habe nur geraten ...)

Es ist sehr wahrscheinlich, dass compareTo und equals falsch sind. Es ist noch nicht ganz klar, wo genau der Fehler liegt, da die Semantik beider Methoden von den Methoden compareTo und equals der Klasse Boeking abhängt.

Die erste if-Anweisung von Ticket.compareTo sieht sehr verdächtig aus. Es sieht so aus, als ob return 1; t1.compareTo(t2) und t2.compareTo(t1) dazu bringen könnte 1 für einige Tickets t1 und t2 ... zurückzugeben und das wäre definitiv falsch.

    
Stephen C 08.08.2010 01:53
quelle

Tags und Links