Sorting values means arranging them in a particular order. The order may be ascending or descending. When the term sorting refers to a Map, it may be sorted on the basis of its keys or values. It depends completely on the requirement.
Java 8 provides a convenient method to sort a map. Using this method will cut down the lines of code used by traditional methods of using java.util.TreeMap
or java.util.Comparator
to some extent.
Sorting By Keys
When a map is sorted by its keys, then its keys are compared and arranged according to the type of sorting required (ascending or descending) and the values are also arranged accordingly. For Example, if the Map [c=2, z=9, d=4, a=6] is sorted on its keys in ascending order, the map is re-arranged to [a=6, c=2, d=4, z=9].
static void sortByKey() {
Map unsortedMap = new LinkedHashMap<>();
unsortedMap.put("K1", 20);
unsortedMap.put("K3", 5);
unsortedMap.put("K9", 6);
unsortedMap.put("K2", 10);
System.out.println("Unsorted Map is : "+unsortedMap);
Map sortedMap = new LinkedHashMap();
unsortedMap.entrySet().stream()
.sorted(Map.Entry. comparingByKey())
.forEachOrdered(x -> sortedMap.put(x.getKey(), x.getValue()));
System.out.println("Sorted Map is : "+sortedMap);
}
Output :
Unsorted Map is : {K1=20, K3=5, K9=6, K2=10}
Sorted Map is : {K1=20, K2=10, K3=5, K9=6}
Explanation :
Java 8 has introduced the concept of stream where in you can get a stream with a collection as its source. Stream provides many methods to perform operations on the collection. Stream is defined by java.util.stream.Stream
interface and can be retrieved by calling stream()
method on any linear collection.
In the above method, the code which does the sorting is :
unsortedMap.entrySet().stream() .sorted(Map.Entry. comparingByKey()).
forEachOrdered(x -> sortedMap.put(x.getKey(), x.getValue()));
Let’s change it from one liner to step wise for the purpose of understanding.
1. Stream> stream = unsortedMap.entrySet().stream();
2. Stream>stream2 = stream.sorted(Map.Entry.comparingByKey());
3. stream2.forEachOrdered(x -> sortedMap.put(x.getKey(), x.getValue()));
The above steps may be explained as :
- In the first step, we get a stream of map entries by calling
stream()
on map’s entry set asunsortedMap.entrySet().stream()
which returns ajava.util.stream.Stream
. This stream has a methodsorted()
which takes an object of typejava.util.Comparator
. - Now, java 8 has added a new static method
comparingByKey()
to the interfacejava.util.Map.Entry
which returns a comparator that compares map’s entry on its key. Combining both the above steps, we get a stream whose elements are sorted by keys. - In Step 3, we iterate over the sorted stream by using its
forEachOrdered
method. This method iterates over the stream in the same order in which the elements flow through the stream and takes an object of typejava.util.function.Consumer
interface. This is a functional interface having only one method. As such we pass it a Lambda expression which populates a new Map with the elements of the stream in the order of sorting of its keys.
Note : If you are still having trouble in understanding the above code, then try below code snippet without Generic declarations as they make the code more difficult to read and understand. Apply Generics when you grasp the concept.
Map sortedMap = new LinkedHashMap();
Stream stream = unsortedMap.entrySet().stream();
//here generics is required otherwise next line will give a compiler error. Just try removing…
Stream> stream2 = stream.sorted(Map.Entry. comparingByValue());
stream2.forEachOrdered(x -> sortedMap.put(x.getKey(), x.getValue()));
Sorting By Values
When a map is sorted by its values, then its values are compared and arranged according to the type of sorting required (ascending or descending) and the keys are also arranged accordingly. For Example, if the Map [c=2, z=9, d=4, a=6] is sorted on its values in ascending order, the map is re-arranged to [c=2, d=4, a=6, z=9].
static void sortByValue() {
Map unsortedMap = new LinkedHashMap<>();
unsortedMap.put("K1", 20);
unsortedMap.put("K3", 5);
unsortedMap.put("K9", 6);
unsortedMap.put("K2", 10);
System.out.println("Unsorted Map is : "+unsortedMap);
Map sortedMap = new LinkedHashMap();
unsortedMap.entrySet().stream()
.sorted(Map.Entry. comparingByValue())
.forEachOrdered(x -> sortedMap.put(x.getKey(), x.getValue()));
System.out.println("Sorted Map is : "+sortedMap);
}
Output :
Unsorted Map is : {K1=20, K3=5, K9=6, K2=10}
Sorted Map is : {K3=5, K9=6, K2=10, K1=20}
Explanation :
In the above method, the code which does the sorting is :
unsortedMap.entrySet().stream().sorted(Map.Entry. comparingByValue()) .forEachOrdered(x -> sortedMap.put(x.getKey(), x.getValue()));
Let’s change it from one liner to step wise for the purpose of understanding.
1. Stream> stream = unsortedMap.entrySet().stream();
2. Stream>stream2 = stream.sorted(Map.Entry.comparingByValue());
3. stream2.forEachOrdered(x -> sortedMap.put(x.getKey(), x.getValue()));
The above steps may be explained as :
- In the first step, we get a stream of map entries by calling
stream()
on map’s entry set asunsortedMap.entrySet().stream()
which returns ajava.util.stream.Stream
. This stream has a methodsorted()
which takes an object of typejava.util.Comparator
. - Now, java 8 has added a new static method
comparingByValue()
to the interfacejava.util.Map.Entry
which returns a comparator which compares map’s entry on its value. Combining both the above steps, we get a stream whose elements are sorted by value. - In Step 3, we iterate over the sorted stream by using its
forEachOrdered
method. This method iterates over the stream in the same order in which the elements flow through the stream and takes an object of typejava.util.function.Consumer
interface. This is a functional interface having only one method. As such we pass it a Lambda expression which populates a new Map with the elements of the stream in the order of sorting of its values.
Let’s tweak in :
- In both the above methods, the map which contains the sorted key-values is taken to be of type
java.util.LinkedHashMap
. This is because LinkedHashMap preserves the order in which the elements are inserted into it. Thus, it will contain the elements in their order of sorting. - Starting java 8 it is possible to have
static
anddefault
methods in interfaces. - The methods
comparingByKey()
andcomparingByValue()
must be called on elements which are mutually comparable otherwise ajava.lang.ClassCastException
will be thrown.
For any doubts, further clarifications, feedback…do make use of the space provided below.