2013-11-26 6 views
5

Warum funktioniert die Oracle Java-API-Dokumentation für die add() Methode für TreeSet und HashSet heißt es:Konventionen in Java Dokumentation verwendet

ein Element e nur hinzugefügt wird, wenn es keine e2 in der Menge ist, wo (e==null ? e2==null : e.equals(e2))

jedoch TreeSet verwendet compareTo(), während HashSethashCode() verwendet Gleichheit zu bestimmen. Beide ignorieren den Wert equals(). Ich bin besorgt, dass die Dokumentation ungenau ist, oder ist es mein Verständnis von Konvention oder der Algorithmus, der fehlerhaft ist?

Antwort

2

Sie haben Recht, dass die TreeSet-Dokumentation falsch ist.

Sie sind falsch über HashSet, da es equals() verwenden. hashCode() ist nicht für Gleichheitsprüfung verwendet, nur für schnelle Suche.

+0

Wenn hashCode() so eingestellt ist, dass immer derselbe Code zurückgegeben wird, dann scheint das Verhalten von add() von equals() abhängig zu sein. Wenn ich jedoch ein Objekt erzeuge, in dem equals() immer 'true' zurückgibt und hashCode() nicht überschreibt - also für verschiedene Objekte unterschiedlich ist - dann fügt add() mehrere Objekte hinzu. Das Verhalten von add() scheint also komplexer zu sein als in den Dokumenten angegeben. Wie Louis sagt, sind diese Situationen außerhalb des Vertrags, aber ich war an der Umsetzung interessiert (da sie nicht das tat, was sie sagte) - weiß jemand, ob es eine kanonische Spezifikation gibt? – user3038094

+0

@ user3038094 - ich würde empfehlen zu lesen, wie HashMap funktioniert. dann werden Sie verstehen, warum die Methode 'equals()' nicht immer aufgerufen wird. Im allgemeinen Sinn verwendet HashSet _does_ '' equals() 'für die Gleichheitsprüfung. – jtahlborn

+0

Danke jtahlborn - Ich habe deinen Rat befolgt und sehe was du meinst. Wenn der HashCode() anders ist, dann stört der Algorithmus nicht equals(), er verwendet nur equals(), wenn hashCode() gleich ist. Vermutlich liegt das daran, dass hashCode() als schneller zu evaluieren gilt als equals(), oder hat es damit zu tun, dass hashCode() ausgewertet werden muss? Also wäre es besser zu sagen in der Dokumentation: e == null? e2 == null: e.hashCode() == e2.hashCode()? e.hashCode() == e2.hashCode(): e.equals (e2) == 0 – user3038094

1

TreeSet erklärt dies in seinem doc:

Beachten Sie, dass die Bestellung durch einen Satz beibehalten (mit oder ohne eine explizite Komparator vorgesehen ist) mit equals konsistent sein muss, wenn sie die Set-Schnittstelle korrekt zu implementieren ist. (Siehe Vergleich oder Komparator für eine genaue Definition von konsistent mit equals.) Dies ist so, weil die Set-Schnittstelle in Form der equals-Operation definiert ist, eine TreeSet-Instanz jedoch alle Elementvergleiche mithilfe der compareTo (oder compare) -Methode durchführt Elemente, die mit dieser Methode gleichgestellt werden, sind vom Standpunkt der Menge her gleich. Das Verhalten einer Menge ist wohldefiniert, auch wenn ihre Reihenfolge nicht mit Gleichem übereinstimmt; es entspricht nur nicht dem allgemeinen Vertrag der Set-Schnittstelle.

Für HashSet, es ist eine implizite Erwartung des Dokuments, das die Objekte in den Set korrekt umgesetzt werden; Wenn hashCode() nicht korrekt implementiert ist, dann ist es nicht HashSet verletzt seine Spezifikation, aber die Objekte, die daran übergeben werden.

+0

"Das Verhalten einer Menge ist wohldefiniert, auch wenn ihre Reihenfolge nicht mit gleich ist." Das Verhalten ist jedoch nicht so wie in der Dokumentation definiert, darum habe ich mich gewundert. Warum ist die Dokumentation nicht spezifisch (genau)? Es wäre besser zu sagen: e == null? e2 == null: e.compareTo (e2) == 0) – user3038094