Hallo zusammen,
ich habe ein seltsames Verhalten der Klasse HashSet festgestellt. Ich habe ein Objekt, welches ich in das HashSet einfüge, dann etwas verändere und nochmals einfüge. Das genau gleiche Objekt ist dann zwei mal im Set.
Gemäss Dokumentation dürfte das aber nicht passieren:
Ich habe ein kleines Beispiel, um dies zu veranschaulichen:
Die Ausgabe meines Programms zeigt klar, dass die beiden Objekte im Set, die ja genau das gleiche Objekt sind, logischerweise sowohl gleiche Hashwerte haben, als auch equals true ergibt und auch der Term aus der Dokumentation true ergibt, obwohl versprochen wird, dass das Element genau dann nicht eingefügt wird. Eine fehlerhafte Implementation wie ich finde.
Das Problem entsteht offenbar, weil sich der hashCode des Objekts zwischen den Einfügungen verändert hat. Meiner Meinung nach, müsste HashSet (insbesondere gemäss Dokumentation) dies bemerken.
Sehe ich das richtig, dass die Implementierung hier der Dokumentation nicht entspricht, könnte man dies gar einen Bug nennen? Gibt es eine kluge Alternative oder muss ich mein HashSet selber implementieren?
Dankre für alle Ideen
Gruss
Martin
ich habe ein seltsames Verhalten der Klasse HashSet festgestellt. Ich habe ein Objekt, welches ich in das HashSet einfüge, dann etwas verändere und nochmals einfüge. Das genau gleiche Objekt ist dann zwei mal im Set.
Gemäss Dokumentation dürfte das aber nicht passieren:
Adds the specified element to this set if it is not already present. More formally, adds the specified element e to this set if this set contains no element e2 such that (e==null ? e2==null : e.equals(e2))
Ich habe ein kleines Beispiel, um dies zu veranschaulichen:
Java:
import java.util.HashSet;
public class HashSetTest {
public static void main(String[] args) {
HashSet<Element> set = new HashSet<Element>();
Element element = new Element();
set.add(element); // füge einmal ein
element.value = 7;
set.add(element); // füge das gleiche Objekt nochmals ein
System.out.println("Anzahl elemente: "+set.size());
for (Element e:set) {
System.out.println("Element mit value "+e.value);
}
Object[] os = set.toArray();
System.out.println("hash stimmt überein: "+(os[0]==os[1]));
System.out.println("equals ergibt: "+os[0].equals(os[1]));
System.out.println("(e==null ? e2==null : e.equals(e2)) egibt: "+(os[0]==null ? os[1]==null : os[0].equals(os[1])));
}
static class Element extends Object {
public int value = 5;
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof Element))
return false;
return ((Element) o).value == value;
}
@Override
public int hashCode() {
return value;
}
}
}
Die Ausgabe meines Programms zeigt klar, dass die beiden Objekte im Set, die ja genau das gleiche Objekt sind, logischerweise sowohl gleiche Hashwerte haben, als auch equals true ergibt und auch der Term aus der Dokumentation true ergibt, obwohl versprochen wird, dass das Element genau dann nicht eingefügt wird. Eine fehlerhafte Implementation wie ich finde.
Das Problem entsteht offenbar, weil sich der hashCode des Objekts zwischen den Einfügungen verändert hat. Meiner Meinung nach, müsste HashSet (insbesondere gemäss Dokumentation) dies bemerken.
Sehe ich das richtig, dass die Implementierung hier der Dokumentation nicht entspricht, könnte man dies gar einen Bug nennen? Gibt es eine kluge Alternative oder muss ich mein HashSet selber implementieren?
Dankre für alle Ideen
Gruss
Martin