[ACCEPTED]-Having a Multimap sorted on keys only in Java-multimap

Accepted answer
Score: 22

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.

Score: 17

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).

Score: 8

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);
            }
        });
}
Score: 4

Call Multimaps.newMultimap, which gives you the flexibility to 2 create, for example, a Multimap backed by 1 TreeMap whose values are ArrayLists.

Score: 2

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.

Score: 1

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.

Score: 1

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 Multimaps in this case, though.

Score: 0

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