Having a Multimap sorted on keys only in Java
guava, java, multimap, sorting
Solution
`Multimaps.index` returns an `ImmutableListMultimap`, so you wouldn't be able to sort it after creating it. You could, however, first create a sorted copy of your `Iterable<MyObject>` and feed that to `Multimap.index`... `ImmutableListMultimap` keeps things in the same order it was given them.
public static ImmutableMultimap<Integer, MyObject> indexOnScore(Iterable<MyObject> i) {
List<MyObject> sorted = Ordering.natural().onResultOf(myObjectToScore())
.sortedCopy(i);
return Multimaps.index(sorted, myObjectToScore());
}
Another option might be to create a `TreeMultimap` and use `Ordering.arbitrary()` as the `Comparator` for the values.
Problem
I would like to have a `c.g.c.c.Multimap` that is sorted based on keys only. The values shouldn't be sorted. I've tried to build something with guava's `TreeMultimap`, but I can't use it because the value type doesn't implement `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; } } ``` I've thought about getting a `SortedSet` of the keys, then iterating over each of these keys in the sorted set to fetch the various values, but I was hoping using an existing (yet undiscovered) feature in Guava rather than using this kind of hack. Note: I won't make `MyObject` implement `Comparable` because it makes no sense with my actual object. Example of input/output: ``` 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()); } ``` Prints: ``` 1 -> c // or switched with line below 1 -> e 2 -> a 3 -> b // or switched with line below 3 -> d ```