Frage

Ich mag eine SortedSet von Kollektionen haben (Sets selbst, in diesem Fall aber nicht unbedingt im Allgemeinen), dass Art von Sammlung Größe. Dies scheint die Ächtung zu verletzen den Vergleicher konsistent mit equals haben (.) - dh zwei Sammlungen können ungleich sein (durch verschiedene Elemente aufweisen), aber auf den gleichen Wert vergleichen (weil sie die gleiche Anzahl von Elementen haben)

Theoretisch verzeihen kann ich auch in den Komparator Wege setzte Sätze von gleicher Größe zu sortieren, aber die Verwendung der Sorte würde Vorteil, dass nicht nehmen, und es gibt nicht wirklich eine nützliche + intuitive Art und Weise die Kollektionen von gleicher Größe zu vergleichen (zumindest in meinem Fall), so dass wie eine Verschwendung scheint.

Ist dieser Fall einer Inkonsistenz scheint wie ein Problem?

War es hilfreich?

Lösung

Wie ChssPly76 in einem Kommentar schrieb, können Sie hashCode verwenden, um den compareTo Anruf im Fall zu entscheiden, wo zwei Kollektionen haben die gleiche Größe, sind aber nicht gleich. Dies funktioniert gut, außer in dem seltenen Fall, in dem Sie zwei Kollektionen mit der gleichen Größe haben, ist nicht gleich, aber die gleiche hashCode. Zwar sind die Chancen, dass das passiert ziemlich klein, aber es ist denkbar. Wenn Sie wirklich vorsichtig sein wollen, statt hashCode, verwenden System.identityHashCode statt. Dies sollten Sie eine eindeutige Nummer für jede Sammlung, und Sie sollen nicht Kollisionen bekommen.

Am Ende des Tages, das gibt Ihnen die Funktionalität die Sammlungen mit im Set nach Größe sortiert, die in beliebiger Reihenfolge im Fall von zwei Kollektionen mit passender Größe. Wenn das alles ist, was Sie brauchen, ist es nicht viel langsamer als der üblicher Vergleich wäre. Wenn Sie die Bestellung benötigen konsistent zwischen verschiedenen JVM-Instanzen zu sein, wird dies nicht funktionieren, und Sie werden es eine andere Art und Weise zu tun haben.

Pseudo-Code:

if (a.equals(b)) {
    return 0;
} else if (a.size() > b.size()) {
    return 1;
} else if (b.size() > a.size()) {
    return -1;
} else {
    return System.identityHashCode(a) > System.identityHashCode(b) ? 1 : -1;
}

Andere Tipps

SortedSet Schnittstelle erweitert Kern Set und sollte daher entsprechen den Auftrag in Set Spezifikation beschrieben.

Die einzige Möglichkeit, das zu erreichen ist Ihr Elements der equal() Methode Verhalten mit Ihrem Comparator konsistent haben -. Der Grund dafür ist, dass der Kern Set auf Gleichheit während SortedSet basierend arbeitet arbeitet basierend auf dem Vergleich

Zum Beispiel: add() Methode in Kern-Set-Schnittstelle definiert gibt an, dass Sie nicht ein Element zu dem Satz hinzufügen können, wenn bereits ein Element equal() Verfahren, das würde mit diesem neuen Elemente als Argument true zurück. Nun, SortedSet nicht equal() nicht verwendet, verwendet es compareTo(). Also, wenn Ihr compareTo() kehrt false Ihr Element hinzugefügt werden, selbst wenn equals() waren true zurückkehren, so dass der Set Vertrag zu brechen.

Nichts davon ist ein praktisches Problem per se, aber. SortedSet Verhalten ist immer konsistent, auch wenn compare() vs equals() nicht.

  

Dies scheint das Verbot verstoßen   haben den Vergleicher konsistent   mit equals () - das heißt, zwei Sammlungen   ungleich sein kann (durch unterschiedliche aufweist   Elemente), zu vergleichen, sondern auf den gleichen   (Wert, weil sie die gleiche   Anzahl der Elemente).

Es ist nicht erforderlich, entweder angegeben (in der Javadoc) oder impliziert, dass ein Comparator mit einem Objekt-Implementierung von boolean equals(Object) konsistent sein.

Beachten Sie, dass Comparable und Comparator sind eindeutige Schnittstellen mit unterschiedlichen Zwecken. Comparable wird verwendet, um eine ‚natürliche‘, um für eine Klasse zu definieren. In diesem Zusammenhang wäre es eine schlechte Idee für equals sein und compateTo unvereinbar zu sein. Im Gegensatz dazu wird ein Comparator verwendet, wenn Sie eine andere Reihenfolge der natürlichen Ordnung einer Klasse verwendet werden sollen.

EDIT:. Hier ist der komplette Absatz aus dem Javadoc für SortedSet

  

Beachten Sie, dass die Bestellung durch eine beibehalten   sortierten Satz (mit oder ohne eine explizite   Komparator vorgesehen ist) müssen   mit equals konsistent, wenn die sortiert   Satz ist richtig das Set zu implementieren   Schnittstelle. (Siehe Vergleichbar   Schnittstelle oder Vergleicher Schnittstelle für   Eine genaue Definition der konsistenten   Diese mit Gleichgestellten.) Ist so, weil die   Set-Schnittstelle ist in Bezug definiert   das entspricht Betrieb, sondern ein sortiert   Satz führt alle Elemente Vergleiche   unter Verwendung seiner compareTo (oder vergleichen)   Verfahren, so sind zwei Elemente, die   als gleich nach dieser Methode sind, aus   der Standpunkt des sortierten Satzes,   gleich. Das Verhalten eines sortierte Menge   gut definierte, auch wenn seine Bestellung ist   inkonsistent mit equals; es gerade   nicht den allgemeinen Vertrag zu gehorchen   die Set-Schnittstelle.

Ich habe den letzten Satz hervorgehoben. Der Punkt ist, dass eine solche SortedSet funktioniert, wie Sie wahrscheinlich erwarten würde, aber das Verhalten einiger Operationen nicht genau die Set Spezifikation entsprechen ... da die Spezifikation ihr Verhalten in Bezug auf die equals Methode definiert.

So in der Tat, es ist eine erklärte Forderung nach Konsistenz (mein Fehler), aber die Folgen ignorieren sie sind nicht so schlimm, wie Sie vielleicht denken. Natürlich ist es zu entscheiden, ob Sie das tun sollten. Nach meiner Einschätzung sollte es in Ordnung sein, vorausgesetzt, dass Sie den Code gründlich kommentieren und stellen Sie sicher, dass die SortedSet nicht ‚Leck‘.

Allerdings ist es mir nicht klar, dass ein Komparator für Sammlungen, die nur auf Sammlungen „Größe“ sieht funktionieren wird ... aus einer semantischen Perspektive. Ich meine, wollen Sie wirklich sagen, dass alle Sammlungen mit (sagen wir) 2 Elemente gleich sind? Dies bedeutet, dass Ihr Gerät kann immer nur eine Sammlung von einer bestimmten Größe enthält ...

Es gibt keinen Grund, warum ein Comparator sollten die gleichen Ergebnisse wie equals() zurückzukehren. In der Tat wurde der Comparator API eingeführt, weil equals() einfach nicht genug ist: Wenn Sie eine Sammlung sortieren wollen, müssen Sie wissen, ob zwei Elemente sind kleinere oder größere

.

Es ist ein wenig seltsam, dass SortedSet als Teil des Standard-API, um den Vertrag in der Set-Schnittstelle und verwendet den Vergleicher definiert bricht Gleichheit statt der Methode equals zu definieren, aber das ist, wie es ist.

Wenn Ihr eigentliches Problem ist Größe eine Sammlung von Sammlungen zu sortieren nach den containted Sammlungen, Sie sind besser mit einer Liste, die Sie sortieren können Collections.sort (List, Komparator>) verwendet wird;

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top