简体   繁体   中英

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

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

Move the bound ? extends Comparable<? super K> ? extends Comparable<? super K> ? 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>

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

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM