[ACCEPTED]-Having a Multimap sorted on keys only in Java-multimap
Multimaps.index
returns an ImmutableListMultimap
, so you wouldn't be able to 5 sort it after creating it. You could, however, first 4 create a sorted copy of your Iterable<MyObject>
and feed that 3 to Multimap.index
... ImmutableListMultimap
keeps things in the same order it 2 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 1 create a TreeMultimap
and use Ordering.arbitrary()
as the Comparator
for the values.
MultimapBuilder
was introduced in Guava 16:
<K extends Comparable<? super K>, V> ListMultimap<K, V> multimap() {
return MultimapBuilder.treeKeys().linkedListValues().build();
}
That keeps your 5 keys sorted by their natural order (MultimapBuilder::treeKeys
is 4 also overloaded to accept a custom comparator), and 3 the values associated with each key are 2 maintained in a LinkedList
(ArrayList
and HashSet
are among the other 1 options).
Though the OP's specific situation seems 5 to have been answered using immutable multimap 4 building functions, I needed a mutable version 3 of what he was asking for. In case it helps 2 anyone, here's the generic method I ended 1 up creating:
static <K, V> Multimap<K, V> newTreeArrayListMultimap(
final int expectedValuesPerKey)
{
return Multimaps.newMultimap(new TreeMap<K, Collection<V>>(),
new Supplier<Collection<V>>()
{
@Override
public Collection<V> get()
{
return new ArrayList<V>(expectedValuesPerKey);
}
});
}
Call Multimaps.newMultimap, which gives you the flexibility to 2 create, for example, a Multimap backed by 1 TreeMap whose values are ArrayLists.
I'd like to point out that the alternative 5 proposed solution, namely "to create a TreeMultimap and use Ordering.arbitrary() as the Comparator for the values", only works if 4 MyObject doesn't override equals() or hashcode(). Ordering.arbitrary() is 3 inconsistent with equals and uses object 2 identity instead, which makes it not a good 1 idea to use it in conjunction with a TreeSet.
You can do it with TreeMultimap if you use Comparators.
Create 9 a Comparator for the key type and the value type (MyObject
?). Then 8 use create(Comparator keyComparator, Comparator valueComparator) to make the map.
The benefit of using 7 a Comparator over implementing Comparable 6 is that you can make the Comparator specific 5 to the situation that you want with the 4 map and it doesn't effect your object in 3 general. As long as your Comparator is 2 consistent with equals it can do whatever 1 you want.
How about this:
public static Multimap<Integer, MyObject> indexOnScore(Iterable<MyObject> i) {
Multimap<Integer, MyObject> m = Multimaps.index(i, myObjectToScore());
Multimap<Integer, MyObject> sortedKeys = Multimaps.newMultimap(
Maps.<Integer, Collection<MyObject>>newTreeMap(),
new Supplier<Collection<MyObject>>() {
@Override
public Collection<MyObject> get() {
return Lists.newArrayList(); // Or a Set if appropriate
}
}
);
sortedKeys.putAll(m);
return sortedKeys;
}
There would be the overhead 1 of creating two separate Multimap
s in this case, though.
Best solution which always works for me 4 is to use Multimap & TreeMultiMap. this 3 will order results in ascending order on 2 keys even if you have multiple duplicate 1 keys. Solution below:
Multimap<Double, Integer> map= TreeMultimap.create(Ordering.natural().reverse(), Ordering.natural());
if (!map.isEmpty()) {
printMap(map);
}
public static <K, V> void printMap(Multimap<Double, Integer> map) throws Exception {
for (Map.Entry<Double, Integer> entry : map.entries()) {
System.out.println("Key : " + entry.getKey()
+ " Value : " + entry.getValue());
}
}
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.