Ich habe Probleme mit Iterator.remove() auf ein HashSet aufgerufen.
Ich habe eine Reihe von zeitgestempelten Objekten. Bevor ich dem Set ein neues Element hinzufüge, durchlaufe ich das Set, identifiziere eine alte Version dieses Datenobjekts und entferne sie (bevor ich das neue Objekt hinzufüge). Der Zeitstempel ist in hashCode und equals() enthalten, aber nicht in equalsData().
for (Iterator<DataResult> i = allResults.iterator(); i.hasNext();)
{
DataResult oldData = i.next();
if (data.equalsData(oldData))
{
i.remove();
break;
}
}
allResults.add(data)
Das Seltsame ist, dass i.remove() für einige Elemente in der Menge stillschweigend fehlschlägt (keine Ausnahme). Ich habe überprüft
-
Die Zeile i.remove() wird tatsächlich aufgerufen. Ich kann sie vom Debugger aus direkt am Haltepunkt in Eclipse aufrufen und es gelingt mir immer noch nicht, den Zustand von Set
-
DataResult ist ein unveränderliches Objekt, das sich also nicht mehr ändern kann, nachdem es der Menge ursprünglich hinzugefügt wurde.
-
Die Methoden equals und hashCode() verwenden @Override, um sicherzustellen, dass es sich um die richtigen Methoden handelt. Unit-Tests überprüfen, ob sie funktionieren.
-
Dies schlägt auch fehl, wenn ich stattdessen einfach eine for-Anweisung und Set.remove verwende. (z. B. Schleife durch die Elemente, finden Sie das Element in der Liste, dann rufen Sie Set.remove(oldData) nach der Schleife).
-
Ich habe mit JDK 5 und JDK 6 getestet.
Ich dachte, ich müsste etwas Grundlegendes übersehen haben, aber nachdem wir einige Zeit damit verbracht haben, sind mein Kollege und ich ratlos. Haben Sie Vorschläge, was man überprüfen könnte?
EDIT:
Es gab Fragen - ist DataResult wirklich unveränderlich. Ja. Es gibt keine Setzer. Und wenn das Date-Objekt abgerufen wird (das ein veränderbares Objekt ist), wird eine Kopie davon erstellt.
public Date getEntryTime()
{
return DateUtil.copyDate(entryTime);
}
public static Date copyDate(Date date)
{
return (date == null) ? null : new Date(date.getTime());
}
FURTHER EDIT (einige Zeit später): Für das Protokoll - DataResult war nicht unveränderlich! Es verwies auf ein Objekt, das einen Hashcode hatte, der sich änderte, wenn es in der Datenbank gespeichert wurde (schlechte Praxis, ich weiß). Es stellte sich heraus, dass sich der Hashcode von DataResult änderte, wenn ein DataResult mit einem transienten Unterobjekt erstellt wurde und das Unterobjekt persistiert wurde.
Sehr subtil - ich habe mir das mehrmals angeschaut und nicht bemerkt, dass es nicht unveränderbar ist.
0 Stimmen
Zwei Möglichkeiten. 1. Sie sagen, dass DataResult unveränderlich ist. Kann man davon ausgehen, dass die Werte durch den Konstruktor gesetzt werden und es keine Set-Methoden gibt? 2. Ihre Gleichheits- und Hashcodes funktionieren nicht so, wie Sie es erwarten. Können Sie den Code für diese beiden posten?