2010-12-14 5 views
2

In Java 6 verstehe ich, dass Sie einem TreeSet einen Comparator liefern können, wenn Sie ihn erstellen, um die "natürliche Reihenfolge" der Objekte in der Menge zu überschreiben.Warum können wir TreeSet einen Comparator zur Verfügung stellen, Hasher aber nicht HashSet?

Haben Sie irgendwelche Gedanken, warum Java die Bereitstellung eines "Hasher" nicht unterstützt, der das "natürliche Hashing" von Objekten im Set außer Kraft setzt?

EDIT: Erhalten von Eingabe von Ihnen könnte mir helfen, beim Entwickeln von APIs in der Zukunft.

Danke.

+1

Die API ist, was es ist. Die Frage nach dem "Warum" kann nur Spekulation sein. – skaffman

+1

Sie könnten die gleiche Frage für Set und Equals stellen. – Ralph

+0

+1 @Ralph, witzig! – Russell

Antwort

2

Hier sind einige mögliche Gründe:

  • Einfachheit - die meisten Menschen brauchen nicht mehrere Funktionen Hash, so die API einfach zu halten es Sinn macht, auf ein einzelnes Objekt zu verlassen.hashCode() Ansatz

  • Leistung - In der Standard-Bibliothek zumindest HashSets und HashMaps usw. benötigen ziemlich stark optimiert werden, wie sie sind so weit verbreitet. Es macht keinen Sinn, den Overhead des Aufrufs einer separaten "hasher", so klein, dass Overhead sein kann.

  • Privat Felder - dort das Problem ist, dass hashCode() auf privaten Felder verlassen kann, kann es für einige Objekte schaffen externe „hashers“ schwierig sein.

1

Es tut! Schauen Sie sich die Object.hashCode Methode an.

Nachdem ich Ihre Frage noch einmal gelesen habe, bin ich vielleicht zu weit gegangen. Ich sehe jetzt, dass du gesagt hast "übergehe" das natürliche Hshing. Normalerweise überschreiben wir den Hash-Wert auf Objektebene und verzichten auf einen überschreibenden Hasher.

Hashes sollen universeller als Komparatoren sein. Das heißt, Hashes sollten fast immer einheitliche, nicht vertrauenswürdige Werte mit geringen Kollisionswahrscheinlichkeiten erzeugen. Der Container, in dem sie verwendet werden, sollte selten einen spezialisierten Hasher benötigen.

+0

Sie kamen zurück, um die Frage zu beantworten! +1 dafür :) – Russell

2

Ein Hasher Objekt wäre redundant zu der hashCode() Methode in der Object Klasse.

Wenn Sie die Art des Hashings beeinflussen möchten, sollten Sie die auf Object definierte Methode hashCode() außer Kraft setzen. Achten Sie darauf, auch equals(Object) zu überschreiben, da diese beiden immer zusammen gehen sollten.

Eine HashSet oder eine ähnliche Datenstruktur verwendet die Objekte hashCode() Methode, um einen Hash-Wert zu erhalten, um bin-Speicher zu bestimmen. Es wird dann equals() verwenden, um dieses Objekt mit anderen Objekten in demselben Bin zu vergleichen, um Gleichheit zu bestimmen.

Der erzeugte Hash-Code muss für diese spezifische Klasse von Objekten eindeutig sein. Dies kann einfach durch Überschreiben der hashCode()-Methode sichergestellt werden und muss nicht von der Implementierung in die Implementierung geändert werden. Ein Hasher Objekt würde nur verschleiern und keinen zusätzlichen Zweck erfüllen. Ich konnte mir keinen einzigen Anwendungsfall vorstellen, bei dem mehrere Hash-Codes für die Speicherung in verschiedenen Datenstrukturen benötigt würden.

+0

Absolut korrekt, und Ihre Eingabe, warum es einen Komparator und kein Hasher gibt? – Russell

+0

Sie brauchen keinen 'Hasher', wenn es eine' hashCode() 'Methode auf' Object' gibt, die das bereits tut. Wenn 'Object' eine Methode' compareTo() 'enthält, benötigen Sie keinen' Comparator'. –

+0

Sie brauchen einen Komparator, wenn Sie die natürliche Reihenfolge überschreiben möchten, aber ich sehe, woher Sie kommen. Vielen Dank! – Russell

0

Sie können den Hash-Code eines Objekts ändern, indem Sie ihn in ein Objekt einfügen, das den Hash-Code auf Ihre Weise implementiert. Die Annahme besteht darin, dass Sie Objekte möglicherweise auf mehrere Arten sortiert haben möchten, aber nicht über mehrere Hash-Strategien verfügen.

c.f. Trove4j unterstützt Hashing-Strategien für seine HashMap und während ich diese Bibliothek verwende, habe ich oft nur eine benutzerdefinierte Hash-Strategie verwendet, sobald ich mich erinnern kann.