How to sort a map with Java 8

This tutorial will show how to sort Map implementations with the map’s key or value properties.

Introduction

Every approach for sorting a map consists of a few consequent steps, no matter by which map’s property (key/value)n we want to sort Map.

Basic sorting algorithm

Sorting Map algorithm goes like this:

  • First, we convert a Map into a Stream
  • Second, we sort streaming elements
  • Third, we collect sorted elements, and we maintain order by placing elements into the correct data structure (LinkedHashMap)

HashMap entrySet() method in Java

The java.util.HashMap.entrySet() method in Java is used to create a set out of the same elements contained in the HashMap. It returns a set of entries from the HashMap. Alternatively we can create a new set and store the map elements into it.

Sort Map by Keys

public void sortMapByKeys() {

    Map<String, Integer> unsortedMap = new HashMap<>();

    unsortedMap.put("z", 0);
    unsortedMap.put("b", 5);
    unsortedMap.put("a", 6);
    unsortedMap.put("e", 7);
    unsortedMap.put("k", 8);
    unsortedMap.put("f", 9);
    unsortedMap.put("n", 100);
    unsortedMap.put("o", -4);
    unsortedMap.put("m", 2);
    unsortedMap.put("d", 1);

    System.out.println("Unsorted map: ");
    System.out.println(unsortedMap);

    // We need a LinkedHashMap to keep an order of newly returned sorted map.
    Map<String, Integer> result = unsortedMap.entrySet()
        .stream()
        .sorted(Map.Entry.comparingByKey())
        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> oldValue, LinkedHashMap::new));

    // Alternative way
    Map<String, Integer> resultAlternative = new LinkedHashMap<>();
    unsortedMap.entrySet()
        .stream()
        .sorted(Map.Entry.comparingByKey())
        .forEachOrdered(x -> resultAlternative.put(x.getKey(), x.getValue()));

    System.out.println("Sorted map by keys: ");
    System.out.println(result);
    System.out.println(resultAlternative);
}

Output

Unsorted map:
{a=6, b=5, d=1, e=7, f=9, z=0, k=8, m=2, n=100, o=-4}

Sorted map by keys:
{a=6, b=5, d=1, e=7, f=9, k=8, m=2, n=100, o=-4, z=0}
{a=6, b=5, d=1, e=7, f=9, k=8, m=2, n=100, o=-4, z=0}

Order in unsortedMap is not secured. However, after the map sorting with the key, we can see that the map is ordered. The newly created map is placed in LinkedHashMap implementation, which maintains the elements’ order.

Sort Map by Values

public void sortMapByValues() {

    Map<String, Integer> unsortedMap = new HashMap<>();

    unsortedMap.put("z", 0);
    unsortedMap.put("c", 7);
    unsortedMap.put("q", 4);
    unsortedMap.put("a", 6);
    unsortedMap.put("e", 7);
    unsortedMap.put("k", 8);
    unsortedMap.put("n", 100);
    unsortedMap.put("o", -4);
    unsortedMap.put("m", 2);
    unsortedMap.put("d", 1);

    System.out.println("Unsorted map: ");
    System.out.println(unsortedMap);

    // We need a LinkedHashMap to keep an order of newly returned sorted map.
    Map<String, Integer> result = unsortedMap.entrySet()
        .stream()
        .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> oldValue, LinkedHashMap::new));

    // Alternative way
    Map<String, Integer> resultAlternative = new LinkedHashMap<>();
    unsortedMap.entrySet()
        .stream()
        .sorted(Map.Entry.<String, Integer>comparingByValue().reversed())
        .forEachOrdered(x -> resultAlternative.put(x.getKey(), x.getValue()));

    System.out.println("Sorted map by values: ");
    System.out.println(result);

    System.out.println("Sorted map by values (alternative approach): ");
    System.out.println(resultAlternative);
}

Output

Unsorted map:
{q=4, a=6, c=7, d=1, e=7, z=0, k=8, m=2, n=100, o=-4}

Sorted map by values:
{n=100, k=8, c=7, e=7, a=6, q=4, m=2, d=1, z=0, o=-4}

Sorted map by values (alternative approach):
{n=100, k=8, c=7, e=7, a=6, q=4, m=2, d=1, z=0, o=-4}

Order in unsortedMap is not secured. However, after the map is sorted by value, we can see it is in order. The newly created map is kept in LinkedHashMap implementation, which maintains the elements’ order.

Sort special case of Map<Object,Object>

There exist special case in Map sorting. It is when we place Object type into the Map parameters. The Stream can’t sort the Map<Object, Object> directly. To solve this case we need to convert Map<Object, Object> into Map<String, String>. Let’s take a look on the code example below:

Note : If you have better idea for Map sorting, let me know in comments below.

public void sortObjectMap() {

    // Example of the Object map
    Properties properties = System.getProperties();
    Set<Map.Entry<Object, Object>> entries = properties.entrySet();

    System.out.println("Unsorted Object map: ");
    entries.forEach(System.out::println);

    LinkedHashMap<String, String> collect = entries.stream()
        .collect(Collectors.toMap(k -> (String) k.getKey(), e -> (String) e.getValue()))
        .entrySet()
        .stream()
        .sorted(Map.Entry.comparingByKey())
        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> oldValue, LinkedHashMap::new));

    System.out.println("Sorted Object map by keys: ");
    result.forEach((key, value) -> System.out.println(key + " : " + value));
}

Output

Unsorted Object map:
sun.desktop=windows
java.specification.version=8
...

Sorted Object map by keys:
awt.toolkit:sun.awt.windows.WToolkit
file.encoding:UTF-8
file.separator:\
java.awt.graphicsenv:sun.awt.Win32GraphicsEnvironment
...

Conclusion

In this article we have shown how to sort Map by key and by value. As some implementation of Map do not maintain order we created ordered maps with LinkedHashMap.

Eventually we have shown a special case of Map<Object, Object> which require transformation of Object into the string in order to to be compared by key or value.

As always, you can find all our examples on our GitHub project!

This entry was posted in Tutorials and tagged , , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.