2013-02-14 18 views
23

Ich suchte nach etwas, das der Fähigkeit des Java TreeSet ähnelte, einen benutzerdefinierten Vergleicher zur Instanziierungszeit zu erhalten, so dass ich nicht die standardmäßigen Gleichheits- (und Hashcode-) Kriterien des Objekts verwenden musste.Java HashSet mit einem benutzerdefinierten Gleichheits-Kriterium?

Am nächsten kam ich, um meine Objekte in eine private benutzerdefinierte Klasse zu wickeln, aber das scheint hacky :(Dies ist eine Art wiederkehrendes Thema beim Programmieren, also habe ich mich gefragt, ob es schon etwas gibt uns zu nutzen. Vielleicht in den commons Bibliotheken?

Dank

+2

Sie haben HashSet im Titel geschrieben, aber TreeSet im Text? Was möchtest du wissen? – AlexWien

+0

Wenn es oft kommt, dann vielleicht können Sie Ihre eigenen rollen? Guava muss sich Sorgen machen, dass Entwickler APIs missbrauchen, für eine eingeschränkte Nutzung nicht. –

Antwort

10

Nö, haben Sie genau die Lösung, die Sie angeblich gefunden. für TreeSet

Auch zu verwenden, ist es frowned upon ist Vergleichskriterien zu verwenden, die sind nicht kompatibel mit equals:

Beachten Sie, dass die Sortierung durch eine sortierte Menge (unabhängig davon, ob ein expliziter Vergleicher angegeben ist) konsistent mit equals sein muss, wenn die sortierte Menge die Set-Schnittstelle korrekt implementieren soll.

(Ich weiß nicht, über Apache Commons, aber Guava specificallyrejected Anfragen für diese Art der Sache.)

+1

"Ich weiß nichts über Apache Commons, aber Guava lehnte speziell Anfragen für solche Dinge ab". Interessant –

3

Sie sind richtig, wenn Sie eine der Trees (TreeMap, TreeSet) verwenden möchten, Die Objekte, die Sie hinzufügen, müssen Comparable implementieren.

Für primitive Typen hat Java das für Sie gelöst.
Für benutzerdefinierte Objekte haben Sie 3 Möglichkeiten:

  1. Eine der Objekt bereits eine eindeutige ID eines primitiven Typ hat oder ein Typ, der bereits compareTo() (wie String) Dann dieses Feld für compareTo implementiert, wenn die Werte der anderen für die Gleichheit nicht wichtig sind. (Aber dann muss equals() auch nur verwenden, um dies ein Feld)

  2. Verwenden EqualsBuilder von Apache: Diese mit Reflexion arbeitet, und ist nicht die schnellste Lösung

  3. schreiben sie ihre selbst, einige Tutorial lesen, wie man das tun: zB:

Josh Bloch: Effektive 2. Java Edition

Aber vergessen Sie nicht, dass equals() und compareTo() kompatibel sein müssen (und auch hashCode()), so dass Sie den Gleichheitsvertrag nicht verletzen. (Der Vertrag selbst ist weniger verständlich, aber es wird klar, wenn Sie eines davon entspricht tutorials.)

Oder vergessen Sie, dass alle, und verwenden Sie eine HashSet, HashMap.

2

Es gibt ein paar Collections-Frameworks von Drittanbietern, die benutzerdefinierte Gleichheitslogik ermöglichen.Dies ist perfekt für das Überschreiben von Gleichheit für Objekte, die die Quelle nicht ändern können.

Trove der Karten/Sets unterstützen die Verwendung von Strategien individuelle Hashing Sie stimmen Sammlungen basierend auf Eigenschaften des Eingangs Daten ermöglicht. Mit dieser Funktion können Sie auch Hash-Funktionen definieren, wenn es nicht möglich ist, Object.hashCode() zu überschreiben.

Um dies zu achive, jede Art, die eine Standard-Korrektur muss, muss die Schnittstelle EqualsAndHashCorrection HE-Collection implementieren. Diese Schnittstelle definiert die Methoden hashCodeInHeCollection() und equalsInHeCollection (Object), die als Korrektur für die falsch implementierten Methoden hashCode() und equals (Object) dienen.

Verwandte Themen