There are multiple ways to sort a list in Java 8, for example, you can get a stream from the List and then use the sorted() method of Stream class to sort a list like ArrayList, LinkedList, or Vector and then convert back it to List. Alternatively, you can use the Collections.sort() method to sort the list. There is also a sort() method added to the List class itself. The Collections.sort() method is an older one and it's available from JDK 1.0 itself but List.sort() is a new method added in Java 8. This method accepts a Comparator if you want to sort a List in a custom order, otherwise, you can pass null if you want to sort a List on the natural order of their elements.
For example, if you have a List of String then by calling List.sort(null), you can sort them in lexicographic order. Similarly, if you have a List of Integer objects then you can sort them into ascending order by calling the List.sort(null) method.
Java 8 not only made the natural order sorting of elements in List easier it also made writing your Comparator to sort elements in custom order super easy by using lambda expression and new utility methods like comparing() and thenComparing() provided on java.util.Comoparator class in JDK 8.
You don't need to write an Anonymous class to create your Comparator, you can do this by writing a couple of lines of code using a lambda expression as shown in this tutorial of how to write Comparator using lambda expression in Java.
Sorting List in the natural order
Here are three main ways to sort a List in natural or increasing order of elements in Java. We will first see the Stream.sorted() method, then the old one Collections.sort(), and finally the newest way of using List.sort() to sort a given List like ArrayList, LinkedList, or Vector in Java.
1. using Stream
Stream class provides a sorted method that can be used to sort a Stream, once you sort the stream you can collect the result in a List which will be sorted.
List<Integer> unsorted = Arrays.asList(11, 2, 5, 3, 2, 55, 32, 34);
List<Integer> sorted = unsorted.stream()
.sorted()
.collect(Collectors.toList());
Output
unsorted list : [11, 2, 5, 3, 2, 55, 32, 34]
sorted list using Java 8 Stream: [2, 2, 3, 5, 11, 32, 34, 55]
2. Using Collections.sort()
This is the oldest and classic way to sort a List in Java. This method is present from JDK 1.0 and it will work on all Java versions. It's a static method so you can directly call them using class names like Collections.sort() and it will sort in the increasing order of elements or default order whatever is defined by the Comparable method.
List<Integer> unsorted = Arrays.asList(11, 2, 5, 3, 2, 55, 32, 34);
Collections.sort(unsorted);
Output
sorted list using Collections.sort(): [2, 2, 3, 5, 11, 32, 34, 55]
3. Using List.sort()
This is the new way to sort a List in Java and it works from Java 8 and higher version. This was possible because Java 8 allows you to add static and default methods on an interface and the JDK team took advantage of that to define useful utility methods on the popular interfaces like Collection, List, and Map.
This is now preferred way to sort List in Java. It optionally take a comparator which you can provide to change the sorting order, if you want to sort in default order just provide null.
List<Integer> unsorted = Arrays.asList(11, 2, 5, 3, 2, 55, 32, 34);
unsorted.sort(null);
Ouptut:
sorted list using Java 8 List.sort():
[12, 15, 20, 23, 34, 101, 155, 312]
As I said, the List.sort() method expects a Comparator, but you can pass a null value as well. The null means list will be sorted in the natural order of elements.
Sorting List in reverse order - Examples
You just need to use the Comparator.reverseOrder() method to sort the list in reverse order of their natural order, for example sorting a list of integers in descending order or sorting a list of String in reverse lexicographical order or reverse alphabetic and alphanumeric order.
1. using Stream
This is similar to the first method in the previous example, the only change is that we have provided a Comparator to the Stream.sorted() method to influence the sorting order. We have provided Comparator.reverseOrder() which returns a comparator that compares elements in reverse of their natural or default order. For example, if you will sort integers then they will be stored in decreasing order.
List<String> names = Arrays.asList("James", "Mary", "Ken", "Joe");
List<String> reversed = names.stream()
.sorted(Comparator.reverseOrder())
.collect(Collectors.toList());
Output:
unsorted list : [2, 2, 3, 5, 11, 32, 34, 55]
sorted list in reversed order using Java 8 Stream:
[55, 51, 34, 32, 31, 21, 21, 11]
2. using Collections.sort()
Here is another example of sorting List in reverse order. This time, we have used the Collections.sort() method to sort a List of String into reverse order which means they will be sorted in the opposite of lexicographic order as shown below:
List<String> names = Arrays.asList("James", "Mary", "Ken", "Joe");
Collections.sort(names, Comparator.reverseOrder());
Output:
unsorted list of String :
[James, Mary, Ken, Joe]
sorted list in reversed order using Java8 List.sort():
[Mary, Ken, Joe, James]
3. using List.sort()
This is the third example to sort a List like ArrayList in reverse order and this time I have used the newly added static method from the List interface, the List.sort() method which is also the preferred way to sort List from Java 8 and beyond.
List<String> names = Arrays.asList("James", "Mary", "Ken", "Joe");
names.sort(Comparator.reverseOrder());
Output:
unsorted list of String : [James, Mary, Ken, Joe]
sorted list in reversed order using Java8 List.sort():
[Mary, Ken, Joe, James]
You can see from the output that Mary comes first and James comes last, which confirms that elements are sorted in the opposite of lexicographic or alphabetic order.
Sorting List of Object on multiple fields - Examples
Sometimes, you have a list of objects which cannot be compared on just one parameter and you want to sort them on multiple fields. For example, you might have a Book, which needs to be compared by name first, followed by price, and followed by reverse order of publication date to putting the newest book at the top.
This can be easily done in Java by using newly added comparing() and thenComparing() methods on Comparator class in Java. Both of these methods allow you to chain comparators to create sophisticated comparison orders to meet real-world requirements. You can use them to use any object to compare on multiple fields.
In the following example, I have compared Person Java object by name and age, which means you will be given a list of Person, and then you need to sort that into name followed by age order. This means if two people have the same name then the younger person will come first.
// Sorting list using multiple Comparator List<Person> employees = new ArrayList<>(); employees.add(new Person("Gauri", 23)); employees.add(new Person("Gauri", 33)); employees.add(new Person("Meli", 45)); employees.add(new Person("Manoj", 32)); System.out.println("unsorted list of Person : " + employees); // first sort list by name and then by age // using lambda expression to write custom // comparator, earlier we use annonymous class employees.sort((p1, p2) -> { if (p1.getName().equals(p2.getName())) { return p1.getAge() - p2.getAge(); } else { return p1.getName().compareTo(p2.getName()); } }); System.out.println("sorted list of Person by multiple conditions : " + employees); Output: unsorted list of Person : [Person{name=Gauri, age=23}, Person{name=Gauri, age=33}, Person{name=Meli, age=45}, Person{name=Manoj, age=32}] sorted list of Person by multiple conditions : [Person{name=Gauri, age=23}, Person{name=Gauri, age=33}, Person{name=Manoj, age=32}, Person{name=Meli, age=45}]
You can see that we have two persons with names Gauri and now they are sorted by name and age which means a younger person comes first in the list and the oldest person comes last in the list.
If you look closely we have provided the comparison logic to the sort method using a lambda expression, this is an easier way to implement Comparator in Java. You can call it on the fly Comparator using a lambda expression.
But, don't make your mind just yet as there is an even better way to implement Comparator in Java 8. you can further simplify the code by using chaining of Comparators using new Java 8 methods like the Comparing() and thenComparing() method as well as by converting lambda to method reference as shown in the following example:
employees.sort(Comparator.comparing(Person::getName)
.thenComparing(Person::getAge));
System.out.println("sorted list of Person using Comparator.comparing : "
+ employees);
Output:
sorted list of Person using Comparator.comparing :
[Person{name=Gauri, age=23},
Person{name=Gauri, age=33},
Person{name=Manoj, age=32},
Person{name=Meli, age=45}]
You can see how easy it is to write real word comparators in Java to compare objects on multiple fields and sort a list. I highly recommend you to learn essential Java 8 features like lambda and stream and also these newly added library methods. If you need a course, see this list of best lambda and stream courses from Udemy, Pluralsight, and Educative.
Java 8 Sorting list Example
Now that, you have seen all the code and understand the logic behind it, here is the complete Java program which you can build and run at your computer to see sorting of the list in action. You can use this program to sort any kind of List like ArrayList, LinkedList, or Vector and also to play with objects and methods and learn these new API methods like List.sort() and Comparator.comparing() and thenComparing() better:
import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; /** * Java Program to calculate the number of years and months */ public class Java8Demo { public static void main(String[] args) { // sorting list in natural order // e.g. ascending order for integer List<Integer> unsorted = Arrays.asList(11, 2, 5, 3, 2, 55, 32, 34); System.out.println("unsorted list : " + unsorted); // sorting using Stream List<Integer> sorted = unsorted.stream() .sorted() .collect(Collectors.toList()); System.out.println("sorted list using Java 8 Stream: " + sorted); // sorting using Collections.sort() Collections.sort(unsorted); System.out.println("sorted list using Collections.sort(): " + unsorted); // sorting using List.sort() - new method only available in Java 8 List<Integer> random = Arrays.asList(101, 20, 15, 23, 12, 155, 312, 34); System.out.println("unsorted list : " + unsorted); // null means sorting in natural order random.sort(null); System.out.println("sorted list using Java 8 List.sort(): " + random); // sorting list in reversed order // e.g. descending order for list of numbers List<Integer> aList = Arrays.asList(11, 21, 51, 31, 21, 55, 32, 34); System.out.println("unsorted list : " + unsorted); // using Stream List<Integer> reversed = aList.stream() .sorted(Comparator.reverseOrder()) .collect(Collectors.toList()); System.out.println("sorted list in reversed order using Java 8 Stream: " + reversed); // using Collections.sort() Collections.sort(aList, Comparator.reverseOrder()); System.out.println("list in reversed order using Collections.sort(): " + aList); // reverse order sorting using List.sort() List<String> names = Arrays.asList("James", "Mary", "Ken", "Joe"); System.out.println("unsorted list of String : " + names); names.sort(Comparator.reverseOrder()); System.out.println("sorted list in reversed order using Java8 List.sort(): " + names); // Sorting list using multiple Comparator List<Person> employees = new ArrayList<>(); employees.add(new Person("Gauri", 23)); employees.add(new Person("Gauri", 33)); employees.add(new Person("Meli", 45)); employees.add(new Person("Manoj", 32)); System.out.println("unsorted list of Person : " + employees); // first sort list by name and then by age // using lambda expression to write custom // comparator, earlier we use annonymous class employees.sort((p1, p2) -> { if (p1.getName().equals(p2.getName())) { return p1.getAge() - p2.getAge(); } else { return p1.getName().compareTo(p2.getName()); } }); System.out.println("sorted list of Person by multiple conditions : " + employees); // you can furthe simplify the code by using // chaining of Comparator using new Java 8 methods e.g. Comparaing() employees.sort(Comparator.comparing(Person::getName) .thenComparing(Person::getAge)); System.out.println("sorted list of Person using Comparator.comparing : " + employees); } private static class Person { private final String name; private final int age; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } @Override public int hashCode() { int hash = 7; hash = 67 * hash + Objects.hashCode(this.name); hash = 67 * hash + this.age; return hash; } @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final Person other = (Person) obj; if (!Objects.equals(this.name, other.name)) { return false; } if (this.age != other.age) { return false; } return true; } @Override public String toString() { return "Person{" + "name=" + name + ", age=" + age + '}'; } } } Output run: unsorted list : [11, 2, 5, 3, 2, 55, 32, 34] sorted list using Java 8 Stream: [2, 2, 3, 5, 11, 32, 34, 55] sorted list using Collections.sort(): [2, 2, 3, 5, 11, 32, 34, 55] unsorted list : [2, 2, 3, 5, 11, 32, 34, 55] sorted list using Java 8 List.sort(): [12, 15, 20, 23, 34, 101, 155, 312] unsorted list : [2, 2, 3, 5, 11, 32, 34, 55] sorted list in reversed order using Java 8 Stream: [55, 51, 34, 32, 31, 21, 21, 11] list in reversed order using Collections.sort(): [55, 51, 34, 32, 31, 21, 21, 11] unsorted list of String : [James, Mary, Ken, Joe] sorted list in reversed order using Java8 List.sort(): [Mary, Ken, Joe, James] unsorted list of Person : [Person{name=Gauri, age=23}, Person{name=Gauri, age=33}, Person{name=Meli, age=45}, Person{name=Manoj, age=32}] sorted list of Person by multiple conditions : [Person{name=Gauri, age=23}, Person{name=Gauri, age=33}, Person{name=Manoj, age=32}, Person{name=Meli, age=45}] sorted list of Person using Comparator.comparing : [Person{name=Gauri, age=23}, Person{name=Gauri, age=33}, Person{name=Manoj, age=32}, Person{name=Meli, age=45}] BUILD SUCCESSFUL (total time: 0 seconds)
That's all about how to sort a List in Java 8. We have seen three ways to sort a List like ArrayList, LinkedList, or Vector in Java 8 and beyond like in Java 11, 12, 13, or even Java 17. You now have the luxury to use Stream.sorted() method or List.sort() method or you can still use old Collections.sort() method to sort a List in increasing order and Comparator.reverseOrder() to sort in the decreasing order of elements. You can use even use Comparators to sort them on multiple fields.
Other Java 8 and Stream tutorials You may like
f 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
- How to convert List to Map in Java 8 (solution)
- What is the default method in Java 8? (example)
- How to format/parse the date with LocalDateTime in Java 8? (tutorial)
- How to use peek() method in Java 8 (example)
- 20 Examples of Date and Time in Java 8 (tutorial)
- 5 Free Courses to learn Java 8 and 9 (courses)
- How to sort the map by keys in Java 8? (example)
- How to use Stream class in Java 8 (tutorial)
- Difference between abstract class and interface in Java 8? (answer)
- 5 Books to Learn Java 8 from Scratch (books)
- How to use filter() method in Java 8 (tutorial)
- How to sort the may by values in Java 8? (example)
- How to join String in Java 8 (example)
- 7 Best Collections and Stream Courses for Java developers (courses)
P. S. - If you are looking for some free courses to learn recent changes on Java 8 and Java 9 then you can also see this list of Free Java 8 to Java 16 Courses for Programmers.
No comments:
Post a Comment
Feel free to comment, ask questions if you have any doubt.