Alan Cook
Alan Cook

Reputation: 362

Sort Map in Ascending Order by Key

I'm attempting to sort a Map in ascending order based on the keys. Given the Map:

Map<Integer, String> map = new LinkedHashMap<Integer, String>();

map.put(5, "five");
map.put(1, "one");
map.put(3, "three");
map.put(0, "zero");

I would like the order:

0, zero
1, one
3, three
5, five

I wrote the following code to accomplish this:

    public <K, V extends Comparable<? super V>> Map<K, V> sortByKeyInAscendingOrder(Map<K, V> map)
{
    List<Entry<K, V>> list = new ArrayList<>(map.entrySet());
    list.sort(Entry.comparingByKey());

    Map<K, V> result = new LinkedHashMap<>();
    for (Entry<K, V> entry : list) {
        result.put(entry.getKey(), entry.getValue());
    }
    return result;
}

However, when I call sort() I get the following error:

The method sort(Comparator<? super Map.Entry<K,V>>) in the type List<Map.Entry<K,V>> is not applicable for the arguments (Comparator<Map.Entry<Comparable<? super Comparable<? super K>>,Object>>)

I've written similar code (which works fine) to sort by value (changing Entry.comparingByKey() to Entry.comparingByValue() ) but for some reason when I try sorting by key I get the above error.

How can I fix this?

Thanks

Upvotes: 5

Views: 3824

Answers (4)

Ryuzaki L
Ryuzaki L

Reputation: 39998

You can also try using java 8 streams

Map<Integer, String> map = new LinkedHashMap<Integer, String>();

    map.put(5, "five");
    map.put(1, "one");
    map.put(3, "three");
    map.put(0, "zero");

    map = map.entrySet().stream().sorted(Comparator.comparing(Map.Entry::getKey))
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

    System.out.println(map);  //{0=zero, 1=one, 3=three, 5=five}

Or you can use forEach on Map

map.forEach((k,v)->System.out.println(k+"  "+v));

Upvotes: 3

Andy Turner
Andy Turner

Reputation: 140309

You'd need to make K comparable to sort by it; and the bound on V is wrong (but unnecessary anyway).

public <K extends Comparable<? super K>, V> Map<K, V> sortByKeyInAscendingOrder(Map<K, V> map)

Mind you, an easier way might be:

return new LinkedHashMap<>(new TreeMap<>(map));

Or

return map.entrySet().stream()
    .sorted(Entry.comparingKey())
    .collect(toMap(k -> k, v -> v, LinkedHashMap::new));

Upvotes: 4

Manoj Vadehra
Manoj Vadehra

Reputation: 846

How about using a TreeMap? it keeps keys sorted in natural order:

https://docs.oracle.com/javase/7/docs/api/java/util/TreeMap.html

If you need to create it from an existing map, use it's parameterized constructor:

TreeMap<Integer,String> treeMap = new TreeMap<>(map);

because using a HashMap doesn't guarantee order and LinkedHashMap maintains insertion order. To keep map sorted by key, use TreeMap.

Upvotes: 2

rgettman
rgettman

Reputation: 178253

The method comparingByKey requires its key, K type parameter, to be Comparable, not (necessarily) its value, V.

Move the bound ? extends Comparable<? super K> from V to K. Change

<K, V extends Comparable<? super K>>

to

<K extends Comparable<? super K>, V>

It is of course optional to have V be Comparable also, but make that bound refer to itself, not to K:

V extends Comparable<? super V>

Upvotes: 2

Related Questions