Question

Je voudrais avoir une SortedSet des collections (se SETS, dans ce cas, mais pas nécessairement en général), ce genre selon la taille de la collection. Cela semble violer la proscription d'avoir le Comparator être compatible avec equals () -. Par exemple, deux collections peuvent être inégales (en ayant différents éléments), mais comparer à la même valeur (parce qu'ils ont le même nombre d'éléments)

En théorie, je pourrais aussi mettre dans les moyens de comparaison pour trier des ensembles de tailles égales, mais l'utilisation de ce genre négligerait de cela, et il n'y a pas vraiment un moyen utile + intuitive pour comparer les collections de taille égale (au moins, dans mon cas particulier), de sorte que semble comme un déchet.

Est-ce que cas d'incompatibilité semble comme un problème?

Était-ce utile?

La solution

ChssPly76 a écrit dans un commentaire, vous pouvez utiliser hashCode pour décider de l'appel compareTo dans le cas où deux collections ont la même taille, mais ne sont pas égaux. Cela fonctionne très bien, sauf dans les rares cas où vous avez deux collections avec la même taille, ne sont pas égaux, mais ont la même hashCode. Certes, les chances que cela se produise sont assez petits, mais il est concevable. Si vous voulez être très prudent, au lieu de hashCode, utilisez System.identityHashCode à la place. Cela devrait vous donner un numéro unique pour chaque collection, et vous ne devriez pas obtenir les collisions.

A la fin de la journée, cela vous donne la fonctionnalité d'avoir les collections dans le Set trié par taille, avec ordre arbitraire dans le cas de deux collections avec une taille correspondant. Si cela est tout ce que vous avez besoin, ce n'est pas beaucoup plus lent que la comparaison habituelle serait. Si vous avez besoin de l'ordre d'être cohérent entre les différentes instances de JVM, cela ne fonctionnera pas et vous devrez le faire d'une autre manière.

pseudocode:

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;
}

Autres conseils

SortedSet interface étend Set et doivent donc se conformer au contrat décrit dans la spécification de Set.

La seule façon d'y parvenir est d'avoir le comportement de la méthode de equal() de votre élément soit compatible avec votre Comparator -. La raison en est que Set de base fonctionne sur la base de l'égalité alors que SortedSet fonctionne sur la base de comparaison

Par exemple, méthode add() définie dans le noyau Set interface spécifie que vous ne pouvez pas ajouter un élément à l'ensemble s'il est déjà un élément dont la méthode equal() retournerait vrai avec ce nouvel élément comme argument. Eh bien, SortedSet n'utilise pas equal(), il utilise compareTo(). Donc, si vos déclarations de compareTo() false votre élément sera ajouté même si equals() devait revenir true, brisant ainsi le contrat de Set.

Rien de tout cela est un problème pratique en soi, cependant. comportement SortedSet est toujours cohérente, même si compare() vs equals() ne sont pas.

  

Cela semble violer la proscription   d'avoir la cohérence soit Comparator   avec equals () - à savoir, deux collections   peuvent être inégaux (en ayant différents   éléments), mais se comparent à la même   valeur (parce qu'ils ont la même   nombre d'éléments).

Il n'y a pas d'exigence, soit déclaré (dans le Javadoc) ou implicite, qu'un Comparator soit compatible avec la mise en œuvre de boolean equals(Object) d'un objet.

Notez que Comparable et Comparator sont interfaces distinctes avec des fins différentes. Comparable est utilisé pour définir un ordre « naturel » pour une classe. Dans ce contexte, ce serait une mauvaise idée pour equals et compateTo incompatible. En revanche, un Comparator est utilisé lorsque vous souhaitez utiliser un ordre différent de l'ordre naturel d'une classe.

EDIT:. Voici le paragraphe complet de la Javadoc pour SortedSet

  

Notez que l'ordre maintenu par une   ensemble trié (ou non explicite   comparateur est prévu) doit être   compatible avec égaux si le tri   ensemble est d'appliquer correctement l'ensemble   interface. (Voir la Comparable   Interface ou interface de comparateur pour   une définition précise de cohérence   avec égaux.) Il en est ainsi parce que la   Paramétrage de l'interface est définie en termes de   Egaux opération, mais Énuméré   ensemble effectue toutes les comparaisons d'éléments   en utilisant son compareTo (ou comparer)   procédé, de sorte que deux éléments qui sont   jugée égale par cette méthode sont, de   Du point de vue de l'ensemble trié,   égal. Le comportement d'un ensemble est trié   bien définie, même si sa commande est   incompatible avec égaux; c'est juste   ne parvient pas à obéir au contrat général de   l'ensemble d'interface.

Je l'ai mis en évidence la dernière phrase. Le point est qu'un tel SortedSet fonctionnera comme vous le plus attendre probable, mais le comportement de certaines opérations ne correspond pas exactement aux spécifications de Set ... car la spécification définit leur comportement en termes de méthode equals.

Donc, en fait, est une exigence de cohérence déclaré (mon erreur), mais les conséquences de l'ignorer ne sont pas aussi mauvais que vous pourriez penser. Bien sûr, il appartient de décider si vous devez le faire. À mon avis, il devrait être OK, à condition que vous commentez le code à fond et assurez-vous que le SortedSet ne « fuite ».

Cependant, il est clair pour moi que pour les collections qui Comparator ne porte que sur une collection « taille » va travailler ... à partir d'un point de vue sémantique. Je veux dire, est-ce que vous voulez vraiment dire que toutes les collections avec (par exemple) 2 éléments sont égaux? Cela signifie que votre jeu ne peut jamais contenir une collection d'une taille donnée ...

Il n'y a aucune raison pour laquelle un Comparator doit retourner les mêmes résultats que equals(). En fait, l'API Comparator a été introduite parce equals() ne suffit pas: Si vous voulez trier une collection, vous devez savoir si deux éléments sont plus ou moins grande

.

Il est un peu étrange que SortedSet comme une partie de l'API standard rompt le contrat défini dans l'ensemble d'interface et utilise le Comparator pour définir l'égalité au lieu de la méthode equals, mais comment cela est.

Si votre problème réel est de trier une collection de collections en fonction de la taille des collections containted, vous êtes mieux avec une liste que vous pouvez trier en utilisant Collections.sort (Liste COMPARATEUR>);

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top