Avoir une Multimap triés sur les touches uniquement en Java
Je voudrais avoir un c.g.c.c.Multimap
qui est triée en fonction des clés. Les valeurs ne devraient pas être triés. J'ai essayé de construire quelque chose avec la goyave est TreeMultimap
, mais je ne peux pas l'utiliser parce que le type de la valeur n'est pas mise en œuvre Comparable
.
public class MyObject /* doesn't implement Comparable */ {
private String name;
private int score;
//Getters/setters are implemented
public static Function<MyObject,Integer> myObjectToScore {
@Override public Integer apply (MyObject o) { return o.score; }
}
public static Multimap<Integer,MyObject> indexOnScore(Iterable<MyObject> i) {
Multimap<Integer,MyObject> m = Multimaps.index(i, myObjectToScore());
//Do the sort of the keys.
return m;
}
}
J'ai pensé à un SortedSet
des touches, puis en itérant sur chacune de ces touches dans l'ensemble trié pour récupérer les différentes valeurs, mais je m'attendais à l'aide d'un existant (encore inconnue) est une fonction de Goyave, plutôt que d'utiliser ce genre de hack.
Note: je ne vais pas faire MyObject
mettre en œuvre Comparable
parce qu'il n'a pas de sens avec mon objet réel.
Exemple d'entrée/sortie:
Set<MyObject> s = Sets.newHashSet(
new MyObject("a", 2),
new MyObject("b", 3),
new MyObject("c", 1),
new MyObject("d", 3),
new MyObject("e", 1)
); //Assuming constructor MyObject(String name, int score)
for (Map.Entry<Integer, MyObject> e: MyObject.indexedOnScore(s).entries()) {
System.out.printf("%d -> %s%n", e.getKey(), e.getValue().getName());
}
Imprime:
1 -> c //or switched with line below
1 -> e
2 -> a
3 -> b //or switched with line below
3 -> d
- pouvez-vous donner l'exemple d'entrée/sortie
- avez-vous vu download.oracle.com/javase/1.4.2/docs/api/java/util/... ?
- oui, je sais que classe, mais je parle de la Goyave est
Multimap
s, ici, pasMap
. - fait, voir OP.
Vous devez vous connecter pour publier un commentaire.
Multimaps.index
retourne unImmutableListMultimap
, de sorte que vous ne seriez pas en mesure de faire le tri après sa création. Vous pouvez, cependant, d'abord créer une triés copie de votreIterable<MyObject>
et nourrir que deMultimap.index
...ImmutableListMultimap
garde les choses dans le même ordre qu'il a donné.Une autre option pourrait être de créer un
TreeMultimap
et l'utilisationOrdering.arbitrary()
comme leComparator
pour les valeurs.Multimap
dans le même ordre. Il ne copie les données de laIterable
à un intermédiaireList
bien.ImmutableMultimap.builder().orderKeysBy()
avant.Ordering.allEqual()
au lieu deOrdering.arbitrary()
pour les valeurs? La documentation dit: "Retourne une commande qui traite de toutes les valeurs de l'égalité, en indiquant "aucun ordre."TreeMultimap
utilise unTreeSet
pour ses valeurs, et si toutes les valeurs sont considérés comme égal, il ne finissent par ne contenant que des un de ces valeurs par clé. Aussi,Ordering.allEqual()
a été ajouté dans la Goyave 13, plus d'un an après que j'ai répondu à cette question. =PMultimapBuilder
a été introduit dans la Goyave 16:Qui garde vos clés triés en fonction de leur ordre naturel (
treeKeys()
est aussi surchargé d'accepter une coutume de comparaison), et les valeurs associées à chaque touche sont maintenus dans unLinkedList
(ArrayList
etHashSet
sont parmi les autres options).Si l'OP, la situation semble avoir été entendu à l'aide de immuable multimap fonctions de construction, j'ai besoin d'une mutable version de ce qu'il demandait. Dans le cas où il aide à quelqu'un, voici le générique de la méthode que j'ai fini par créer:
Appel Multimaps.newMultimap, qui vous donne la souplesse nécessaire pour créer, par exemple, une Multimap soutenu par TreeMap dont les valeurs sont ArrayLists.
Je tiens à souligner que la solution de rechange solution proposée, à savoir "pour créer un TreeMultimap et l'utilisation de la Commande.arbitraire() comme point de Comparaison pour les valeurs", ne fonctionne que si MyObject ne pas remplacer equals() ou hashcode(). De la commande.arbitraire() est incompatible avec d'égal à égal et utilise l'identité de l'objet au lieu de cela, ce qui rend-il pas une bonne idée de l'utiliser en conjonction avec un TreeSet.
Comment à ce sujet:
Il y aurait de la surcharge de la création de deux
Multimap
s dans ce cas, si.Multimap
s.Vous pouvez le faire avec TreeMultimap si vous utilisez des Comparateurs.
Créer un Comparateur pour le type de clé et le type de la valeur (
MyObject
?). Ensuite, utilisez créer(Comparateur de keyComparator, Comparateur valueComparator) pour faire la carte.L'avantage d'utiliser un Comparateur sur la mise en œuvre de Comparable, c'est que vous pouvez faire le Comparateur spécifiques à la situation que vous voulez avec la carte et il n'a pas d'effet de votre objet en général. Tant que votre Comparateur est compatible avec égal à égal, il peut faire ce que vous voulez.
MyObject
mettre en œuvreComparable
. Une extension de cette déclaration est que je me suis logiquement n'ont pas un "défaut"Comparator
pourMyObject
ainsi. Mon but est vraiment d'avoir une Multimap qui a ses clés triés, mais les valeurs de l'une des touches ne devrait pas être triés.Meilleure solution qui fonctionne toujours pour moi est d'utiliser Multimap & TreeMultiMap. cela permettra de trier les résultats par ordre croissant sur les touches même si vous disposez de plusieurs doubles de clés. La Solution ci-dessous: