Java List of Map objects sort

In the past, I have shown you how to sort a HashMap by values in Java, but that was using traditional techniques of the pre-Java 8 world. Now the time has changed and Java has evolved into a programming language that can also do functional programming. How can you, a Java Programmer take advantage of that fact to do your day-to-day task better like how do you sort a Map by values in Java using lambda expressions and Stream API. That's what you are going to learn in this article. It will serve two purposes, first, it will tell you a new way to sort a Map by values in Java, and, second and more important it will introduce you to essential Java 8 features like Lambda Expression and Streams, which every Java Programmer should learn.

By the way, it's not just the lambda expression and stream which makes coding fun in Java 8, but also all the new API methods added into an existing interface likeComparator, Map.Entrymakes day-to-day coding much easier.

This evaluation of existing interfaces was possible by introducing the non-abstract method on interfaces likedefault methods and static methods.

Because of this path-breaking feature, it's possible to add new methods into the existing Java interface and Java API designers have taken advantage to add much-needed methods on popular existing interfaces.

One of the best examples of this is java.util.Comparator interface which has now got comparing[] and thenComparing[] methods to chain multiple comparators, making it easier to compare an object by multiple fields, which was very tedious and requires a lot of nesting prior to Java 8.

The Map.Entry class, which is a nested static class of java.util.Map interface is also not behind, it has got two additional methods comparingByKey[] and comparingByValue[] which can be used to sort a Map by key and values. They can be used along with thesorted[] method of Stream to sort a HashMap by values in Java.

Btw, if you are new to the Java world then I suggest you start learning from Java 8 itself, no need to learn the old techniques of doing a common task like sorting a list or map, working with date and time, etc and if you need some help, you can also look at comprehensive online Java courses likeThe Complete Java MasterClass, which will not only teach you all this but much more.




1. How to Sort Map by values on Increasing order

You can sort a Map like a HashMap, LinkedHashMap, or TreeMap in Java 8 by using the sorted[] method of java.util.stream.Stream class. This means accepts a Comparator, which can be used for sorting. If you want to sort by values then you can simply use the comparingByValue[] method of the Map.Entry class. This method is newly added in Java 8 to make it easier for sorting.

ItemToPrice.entrySet[] .stream[] .sorted[Map.Entry.comparingByValue[]] .forEach[System.out::println];
Btw, if you need a Map instead of just printing the value into the console, you can collect the result of the sorted stream using thecollect[] method of Stream and Collectors class of Java 8 as shown below:

// now, let's collect the sorted entries in Map Map sortedByPrice = ItemToPrice.entrySet[] .stream[] .sorted[Map.Entry.comparingByValue[]] .collect[Collectors.toMap[e -> e.getKey[],e -> e.getValue[]]];
The Map returned by the previous statement was not sorted because the order was lost while collecting results in Map you need to use the LinkedHashMap to preserve the order

Map sortedByValue = ItemToPrice.entrySet[] .stream[] .sorted[Map.Entry.comparingByValue[]] .collect[toMap[Map.Entry::getKey, Map.Entry::getValue, [e1, e2] -> e1, LinkedHashMap::new]];
This is the right way to sort a Map by values in Java 8 because now the ordering will not be lost as Collector is using LinkedHashMap to store entries. This is also a good example of using constructor references in Java 8. You can read more about that in theCollections to Streams in Java 8 Using the Lambda Expressionscourse on Pluralsight, which provides an in-depth explanation of new Java 8 features.






2. Sorting Map by values on decreasing Order

In order to sort a Map by values in decreasing order, we just need to pass a Comparator which sort it in the reverse order. You can use the reversed[] method of java.util.Comparator purpose to reverse order of a Comparator. This method is also newly added in the Comparator class in JDK 8.

Map sortedByValueDesc = ItemToPrice.entrySet[] .stream[] .sorted[Map.Entry.comparingByValue[].reversed[]] .collect[toMap[Map.Entry::getKey, Map.Entry::getValue, [e1, e2] -> e1, LinkedHashMap::new]];
The key point here is the use of thereversed[] method, the rest of the code is the same as the previous example. In the first step, you get the entry set from the Map, then you get the stream, then you sorted elements of the stream using thesorted[] method, which needs a comparator.

You supply a Comparator which compares by values and then reversed it so that entries will be ordered in the decreasing order.

Finally, you collected all elements into a Map and you asked Collector to use the LinkedHashMap by using constructor reference, which is similar to method reference in Java 8 but instead of using method name, it usesClass::new, that's it. If you are interested, you can learn about it in any good Java 8 book likeJava 8 in Actionby Raul Gabriela Ulmaon Manning publication.





Important points to Remember

Here are some of the important points to remember while sorting a Map by values in Java 8. These are very important for correctly sorting any HashMap or Hashtable as well:
  1. Use LinkedHashMap for collecting the result to keep the sorting intact.
  2. Use static import for better readability e.g. static import Map.Entry nested class.
  3. Use new comparingByKey[] and comparingByValue[] method from Map.Entrythey were added in Java 8 to make sorting by key and value easier in Java.
  4. Use reversed[] method to sort the Map in descending order
  5. Use forEach[] to print the Map
  6. Use Collectors to collect the result into a Map but always use LinkedHashMap because it maintains the insertion order.
You can learn more about lambda expression and method reference used in our example in a good Java 8 course likeThe Complete Java MasterClasson Udemy.





Java Program to Sort the Map by Values in JDK 8

Here is our complete Java program to sort a HashMap by values in Java 8 using a lambda expression, method reference, and new methods introduced in JDK 8 likeMap.Entry.comparingByValue[] method, which makes it easier to sort the Map by values.

/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package test; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import java.util.stream.Collectors; import static java.util.stream.Collectors.*; /** * * @author Javin Paul */ public class SortingMapByValueInJava8 { /** * @param args * the command line arguments */ public static void main[String[] args] { // Creating a Map with electoric items and prices Map ItemToPrice = new HashMap[]; ItemToPrice.put["Sony Braiva", 1000]; ItemToPrice.put["Apple iPhone 6S", 1200]; ItemToPrice.put["HP Laptop", 700]; ItemToPrice.put["Acer HD Monitor", 139]; ItemToPrice.put["Samsung Galaxy", 800]; System.out.println["unsorted Map: " + ItemToPrice]; // sorting Map by values in ascending order, price here ItemToPrice.entrySet[].stream[] .sorted[Map.Entry. comparingByValue[]] .forEach[System.out::println]; // now, let's collect the sorted entries in Map Map sortedByPrice = ItemToPrice.entrySet[].stream[] .sorted[Map.Entry. comparingByValue[]] .collect[Collectors.toMap[e -> e.getKey[], e -> e.getValue[]]]; System.out.println["Map incorrectly sorted by value in ascending order: " + sortedByPrice]; // the Map returned by the previous statement was not sorted // because ordering was lost while collecting result in Map // you need to use the LinkedHashMap to preserve the order Map sortedByValue = ItemToPrice .entrySet[] .stream[] .sorted[Map.Entry. comparingByValue[]] .collect[ toMap[Map.Entry::getKey, Map.Entry::getValue, [e1, e2] -> e1, LinkedHashMap::new]]; System.out.println["Map sorted by value in increasing order: " + sortedByValue]; // sorting a Map by values in descending order // just reverse the comparator sorting by using reversed[] method Map sortedByValueDesc = ItemToPrice .entrySet[] .stream[] .sorted[Map.Entry. comparingByValue[].reversed[]] .collect[ toMap[Map.Entry::getKey, Map.Entry::getValue, [e1, e2] -> e1, LinkedHashMap::new]]; System.out.println["Map sorted by value in descending order: " + sortedByValueDesc]; } } Output unsorted Map: {Samsung Galaxy=800, HP Laptop=700, Sony Braiva=1000, Acer HD Monitor=139, Apple iPhone 6S=1200} Acer HD Monitor=139 HP Laptop=700 Samsung Galaxy=800 Sony Braiva=1000 Apple iPhone 6S=1200 Map incorrectly sorted by value in ascending order: {Samsung Galaxy=800, HP Laptop=700, Sony Braiva=1000, Acer HD Monitor=139, Apple iPhone 6S=1200} Map sorted by value in increasing order: {Acer HD Monitor=139, HP Laptop=700, Samsung Galaxy=800, Sony Braiva=1000, Apple iPhone 6S=1200} Map sorted by value in descending order: {Apple iPhone 6S=1200, Sony Braiva=1000, Samsung Galaxy=800, HP Laptop=700, Acer HD Monitor=139}

You can see that the map is sorted now by values, which are integers. In this first example, we have printed all entries in sorted order and that's why Acer HD Monitor comes first because it is least expensive, while Apple iPhone comes last because it is most expensive.

In the second example, even though we sorted in the same way as before, the end result is not what you have expected because we failed to collect the result into a Map which keeps them in the order they were i.e. we should have used LinkedHashMap, which keeps entries in the order they were inserted.

In the third and fourth examples, we rectified our mistake and collected the result of the sorted stream into a LinkedHashMap, hence we have entries in sorted order. In the last example, sort entries in descending order hence, Apple comes first and Acer comes last.

Here is a one-liner in Java 8 to sort a HashMap by values:



That's all about how to sort a Map by values in Java 8. you can use this technique to sort any Map implementations like HashMap, Hashtable, ConcurrentHashMap, TreeMap,etc. If you don't need to print the values or perform any operation, but you just need a sorted Map then make sure you use thecollect[] method to store sorted entries into another Map.

Also, when you use the Collector to collect elements from sorted Stream, make sure you use LinkedHashMap to collect the result, otherwise ordering will be lost.



Other Java 8 Tutorials you may like
If you are interested in learning more about the new features of Java 8, here are my earlier articles covering some of the important concepts of Java 8:
  • Top 5 Courses to Learn Java 8 Programming [courses]
  • 5 Books to Learn Java 8 from Scratch [books]
  • How to join String in Java 8 [example]
  • How to use filter[] method in Java 8 [tutorial]
  • Java 8 map + filter + stream example [tutorial]
  • How to use Stream class in Java 8 [tutorial]
  • 5 Free Java 8 and Java 9 courses for Programmers [courses]
  • How to use forEach[] method in Java 8 [example]
  • How to convert List to Map in Java 8 [solution]
  • 20 Examples of Date and Time in Java 8 [tutorial]
  • How to format/parse the date with LocalDateTime in Java 8? [tutorial]
  • How to use peek[] method in Java 8 [example]
  • How to sort the map by keys in Java 8? [example]
  • 10 examples of Options in Java 8? [example]
  • Top 5 websites to learn Java Coding for FREE [websites]

Thanks for reading this tutorial so far. If you like this example of sorting HashMap in Java 8 using lambda expression then please share it with your friends and colleagues. If you have any questions, feedback, or suggestion then please drop a comment.

P. S. - If your goal is to learn new features introduced in Java 8 then you can also check out thefree Java 8 courseswhich only focus on new features and nothing else.

Video liên quan

Chủ Đề