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 aStream
- 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!