Wann sollte ich eine Hash-Code-Funktion für meine Typen definieren?

8

Gibt es einen anderen Grund für die Implementierung einer Hash-Code-Funktion für meine Typen als die Verwendung von Hash-Tabellen?

Nehmen wir an, ich entwerfe einige Typen, die ich intern verwenden möchte. Ich weiß, dass Typen "intern" für das System sind, und ich weiß auch, dass ich diese Typen niemals in Hashtabellen verwenden werde. Trotzdem entscheide ich, dass ich die equals () Methode neu definieren muss.

Die Theorie sagt, ich sollte auch die Hash-Code-Methode neu definieren, aber ich kann keinen Grund sehen, warum ich das in diesem Fall tun sollte.

Kann mir jemand einen anderen Grund nennen?

Diese Frage kann umformuliert werden zu: In welchen Situationen sollten wir eine Hash-Code-Methode in unseren Typen implementieren?

PS: Ich frage nicht, wie man einen implementiert. Ich frage wann .

    
devoured elysium 13.06.2010, 21:16
quelle

4 Antworten

10

Sie könnten nicht - aber wird irgendein Code, zum Beispiel, LINQ verwenden? Es gibt eine Reihe von unerwarteten Orten, die möglicherweise eine Hashmappe oder ein Wörterbuch für Ihre Daten verwenden.

Wenn Sie nicht unerwartet ... "Spaß" wollen, dann überschreiben Sie Equals , wenn Sie GetHashCode ändern. Ebenso sollte jede IEquatable<T>.Equals mit der object.Equals Implementierung übereinstimmen.

    
Marc Gravell 13.06.2010, 21:19
quelle
6

Ja, definitiv. hashCode und equals sind 2 Views zum selben Thema und müssen konsistent sein. Viele Routinen in den Collections verwenden den Hashcode und beginnen sich schlecht zu benehmen, wenn sie andere Dinge als Gleiches sagen. Man kann "sich schlecht benehmen" als "unglaublich schwer zu findende Käfer, die zu frühem Haarverlust führen" lesen.

Wenn Sie Equals überschreiben, müssen Sie den Hashcode außer Kraft setzen, nicht weil die Richtlinie dies sagt, sondern weil Sie Ihr Haar (oder Ihre Zeit) schätzen.

Moderne IDEs erzeugen guten equals / hashcode für Sie und der EqualsBuilder / HashCodeBuilder von Java Commons oder Spring kann Ihnen dabei helfen. Projekt Lombok erzeugt sie während der Fahrt.

Das ist eine ernste Sache, und das Beste, was Sie mit diesen Methoden tun können, ist, es richtig zu machen, und es gibt Hunderte von Möglichkeiten, es falsch zu machen, was zu Schmerzen und Agonie führt. Wenn Sie vermeiden können, sie selbst zu schreiben, tun Sie dies, verwenden Sie einen der Generatoren oder Bibliotheken, um Ihnen zu helfen.

    
Peter Tillemans 13.06.2010 21:23
quelle
4
  

In welchen Situationen sollten wir eine Hash-Code-Methode in unseren Typen implementieren?

Kurze Antwort: Immer wenn Sie .Equals überschreiben. Weil die Framework Design Guidelines das sagen.

    
dtb 13.06.2010 21:18
quelle
0

Wenn Sie wirklich sicher sind, dass Ihre Objekte nicht in einer Hashtabelle verwendet werden und dieser Hashcode nicht verwendet wird, können Sie HashCode überschreiben, um eine Ausnahme "nicht implementiert" auszulösen. Dies ist sicherer als nicht überschreiben, da es die Verwendung der Methode explizit verbietet und die hervorstechenden Fehler vermeidet, die andernfalls entstehen würden. Es zeigt Ihnen auch deutlich, wenn die Methode tatsächlich verwendet wird.

Aber ich würde persönlich sagen, verwenden Sie einfach die IDE, um eine vernünftige Implementierung zu erzeugen, die mit Equals konsistent ist und damit gemacht wird. In der Regel überschreiben Value-Typen den Wert "equals". Beim Testen werden in der Regel Maps verwendet. Daher ist es sinnvoll, den vollständigen Vertrag zu implementieren, der von der equals / hashcode-API benötigt wird.

    
mdma 13.06.2010 21:24
quelle

Tags und Links