Sort custom object list in Java 8

Java provides a number of ways to sort a list.   In this article, we'll demonstrate how to sort a list of objects by field.

We'll use the following User class in our examples:

package com.example.demo; import java.util.Date; public class User { private long id; private String email; private Date createdOn; // other getters and setters omitted public Date getCreatedOn() { return createdOn; } public void setCreatedOn(Date createdOn) { this.createdOn = createdOn; } }

Suppose we have a service method that returns a list of all users:

List<User> users = userService.getAllUsers();

So we have a list of users and want to sort them by createdDate. 

Let's cover several different approaches and explore the benefits and limitations of each. 

Option 1: Collections.sort() with Comparable

We can use the Comparable interface to define the default sort criteria for a class.   

This requires implementing the compareTo() method as seen on lines 20-26 below:

package com.example.demo; import java.util.Date; public class User implements Comparable<User> { private long id; private String email; private Date createdOn; // other getters and setters omitted public Date getCreatedOn() { return createdOn; } public void setCreatedOn(Date createdOn) { this.createdOn = createdOn; } @Override public int compareTo(User u) { if (getCreatedOn() == null || u.getCreatedOn() == null) { return 0; } return getCreatedOn().compareTo(u.getCreatedOn()); } }

Sort by created date descending

Collections.sort(users); Collections.reverse(users);

This option requires modifying our class and defining a default (or natural) sort order. Sorting in descending order requires two separate method calls.

This option doesn't allow for sorting on a different field other than the one we chose.

Option 2: Collections.sort() with Comparator 

Instead of modifying our class, we can pass in a comparator to Collections.sort().  The examples below create a comparator using an anonymous class. 

Sort by created date ascending

Collections.sort(users, new Comparator<User>() { @Override public int compare(User u1, User u2) { return u1.getCreatedOn().compareTo(u2.getCreatedOn()); } });

Sort by created date descending

We swap the order of u1 and u2 to reverse the sort order.

Collections.sort(users, new Comparator<User>() { @Override public int compare(User u1, User u2) { return u2.getCreatedOn().compareTo(u1.getCreatedOn()); } });

This option allows code outside the class to dictate the sort criteria and order. 

However, it requires an ugly anonymous class that isn't very readable.

Option 3: List interface sort() [Java 8]

Java 8 introduced a sort method in the List interface which can use a comparator.

The Comparator.comparing() method accepts a method reference which serves as the basis of the comparison.  So we pass User::getCreatedOn to sort by the createdOn field. 

Sort by created date ascending

users.sort(Comparator.comparing(User::getCreatedOn));

Sort by created date descending

users.sort(Comparator.comparing(User::getCreatedOn).reversed());

As we can see, the code becomes much simpler and easier to read.

Option 4: Stream interface sorted() [Java 8]

Suppose we didn't want to modify the original list, but return a new sorted list. 

In this situation, we can use the sorted() method from the Stream interface introduced in Java 8.

Return new list sorted by created date ascending

List<User> sortedUsers = users.stream() .sorted(Comparator.comparing(User::getCreatedOn))   .collect(Collectors.toList());

Return new list sorted by created date descending

List<User> sortedUsers = users.stream() .sorted(Comparator.comparing(User::getCreatedOn).reversed())   .collect(Collectors.toList());

While each of the options discussed performs the sorting, the last two options are recommended because they are easier to code, debug, and read. 

accumulo,1,ActiveMQ,2,Adsense,1,API,37,ArrayList,18,Arrays,24,Bean Creation,3,Bean Scopes,1,BiConsumer,1,Blogger Tips,1,Books,1,C Programming,1,Collection,8,Collections,37,Collector,1,Command Line,1,Comparator,1,Compile Errors,1,Configurations,7,Constants,1,Control Statements,8,Conversions,6,Core Java,149,Corona India,1,Create,2,CSS,1,Date,3,Date Time API,38,Dictionary,1,Difference,2,Download,1,Eclipse,3,Efficiently,1,Error,1,Errors,1,Exceptions,8,Fast,1,Files,17,Float,1,Font,1,Form,1,Freshers,1,Function,3,Functional Interface,2,Garbage Collector,1,Generics,4,Git,9,Grant,1,Grep,1,HashMap,2,HomeBrew,2,HTML,2,HttpClient,2,Immutable,1,Installation,1,Interview Questions,6,Iterate,2,Jackson API,3,Java,32,Java 10,1,Java 11,6,Java 12,5,Java 13,2,Java 14,2,Java 8,128,Java 8 Difference,2,Java 8 Stream Conversions,4,java 8 Stream Examples,12,Java 9,1,Java Conversions,14,Java Design Patterns,1,Java Files,1,Java Program,3,Java Programs,114,Java Spark,1,java.lang,4,java.util. function,1,JavaScript,1,jQuery,1,Kotlin,11,Kotlin Conversions,6,Kotlin Programs,10,Lambda,2,lang,29,Leap Year,1,live updates,1,LocalDate,1,Logging,1,Mac OS,3,Math,1,Matrix,6,Maven,1,Method References,1,Mockito,1,MongoDB,3,New Features,1,Operations,1,Optional,6,Oracle,5,Oracle 18C,1,Partition,1,Patterns,1,Programs,1,Property,1,Python,2,Quarkus,1,Read,1,Real Time,1,Recursion,2,Remove,2,Rest API,1,Schedules,1,Serialization,1,Servlet,2,Sort,1,Sorting Techniques,8,Spring,2,Spring Boot,23,Spring Email,1,Spring MVC,1,Streams,31,String,61,String Programs,28,String Revese,1,StringBuilder,1,Swing,1,System,1,Tags,1,Threads,11,Tomcat,1,Tomcat 8,1,Troubleshoot,26,Unix,3,Updates,3,util,5,While Loop,1,

There are a lot of examples of Sorting ArrayList in Java on the internet, but most of them use either String or Integer objects to explain sorting, which is not enough, because in real-world you may have to sort a list of custom objects like your domain or business objects like Employee, Book, Order, Trade, etc. In order to sort an ArrayList of custom or user-defined objects, you need two things, first a class to provide ordering and a method to provide sorting. If you know about ordering and sorting in Java then you know that the Comparable and Comparator class is used to provide the ordering for objects. 

The Comparable interface provides natural order like the lexicographic order of String or name for Employees, while Comparator is used to provide custom order. It gives you the flexibility to sort your objects on the parameter you want e.g. you can sort a list of Coupon objects on the percentage discount, expiry dates, or based upon the total cost.

Once you have got ordering for your object, you can use Collections.sort() method to sort your ArrayList of objects. This method accepts an ArrayList and sorts them in place. Internally it uses MergeSort to sort your list of objects. 

This method is a good example of a strategy pattern because it uses the Comparator you provide to sort your objects, which means you can sort the same list of objects into different order by just changing the Comparator.

For example, You can sort an ArrayList of Objects in descending order by just reversing the order of your Comparator. The JDK API provides another convenient method Collections.reverseOrder(Comparator c) which returns a comparator with the opposite order of the given Comparator.

Btw, this is not the only way to sort an ArrayList of objects in Java. If you want you can use Comparable to sort in the natural order and in the decreasing order of natural order imposed by Comparator. the JDK 8 release also added a couple of methods on both java.util.Comparator class and java.util.List to make sorting easier.


For example, you can also use List.sort() method to sort a List of objects. This is similar to Collections.sort() and you can use it to sort a list of objects using both Comparator and Comparable. This method accepts a Comparator and sorts elements based upon that, but if you want to sort on the natural order, just don't supply a Comparator and pass null.

The List.sort() of Java 8 will then sort the list on order imposed by Comparable. You can further see these Java 8 Tutorials and courses to learn more about new methods added on the Comparator and List interface to make sorting easier in Java 8.

In this article, I'll show you how to sort a List of objects in both ascending and descending order by using Comparator. I have a domain object called Course, which contains the title and price of the course, a title is a String and the fee is long value. 

In order to sort the list of courses like REST With Spring, Learn Spring Security, and Introduction to Spring MVC 4, some of my recommended courses to learn Spring, I have created two Comparators, a title comparator which sorts based upon the title and a fee comparator which sorts based upon fee.

These Comparator implementation classes use Java 8 lambdas to implement compare() method as shown here, and sort the list of objects into ascending order of title and fee.

In order to sort in the reverse order like descending order, you don't need to create a separator Comparator, instead, you just need to reverse the order of the existing comparator using Collections.reverseOrder(Comparator c) method.

 If you are using Java 8, then you can also use the reversed() method of java.util.Comparator which returns a comparator that imposes the reverse ordering of this comparator.

In fact, JDK 8 has added several new methods to facilitate sophisticated sorting in Java 8 like the comparing() and thenComparing() method to chain multiple comparators. 

You can further see these Java 8 Programming Courses to learn more about sophisticated sorting in Java 8 with new methods of java.util.Comparator class. I'll also write more posts to explain the new features of Comparator in Java 8 to give you an overview of the power you get with Java 8.

Sort custom object list in Java 8

Here is our Java program which will sort the list of courses using custom comparators. In this article, I have created two implementations of java.util.Comparator interface, one called TitleComparator, which sorts the list of courses on their title and other, called FeeComparator which sorts the list of courses on their price.

I have also used the new List.sort() method of JDK 8 for sorting. Though, you can use Collection.sort() if you are not using JDK 8, just replace the List.sort() with Collections.sort() and the program should work fine.

Also, I have used the lambda expression to implement our Comparators as oppose to the Anonymous class which we used earlier. You can see your Comparator implementation has become quite simple and you can write them in just one line.

import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.stream.Collectors; /* * Java Program to sort an ArrayList with objects using Comparator */ public class Main { public static void main(String[] args) { // sorting an ArrayList of object using Comparator Course restWithSpring = new Course("REST with Spring", 99); Course learnSpringSecurity = new Course("Learn Spring Security", 110); Course introToSpringMVC4 = new Course("Introduction to Spring MVC 4", 0); List<Course> listOfCourses = new ArrayList<>(); listOfCourses.add(restWithSpring); listOfCourses.add(learnSpringSecurity); listOfCourses.add(introToSpringMVC4); // let's sort this list of course by title first using Comparator Comparator<Course> titleComparator = (c1, c2) -> c1.title().compareTo(c2.title()); Comparator<Course> feeComparator = (c1, c2) -> (int) (c1.fee() - c2.fee()); // printing ArrayList before sorting System.out.println("unsorted list: " + listOfCourses); // sorting list of objects using comparator - using title on ascending order listOfCourses.sort(titleComparator); // printing ArrayList after sorting in ascending order System.out.println("sorted list in ascending order of title: " + listOfCourses); // sorting arraylist of objects using comparator // - using fee on ascending order listOfCourses.sort(feeComparator); // printing ArrayList after sorting in ascending order System.out.println("sorted list in ascending order of fee: " + listOfCourses); // sorting array list in descending order of title listOfCourses.sort(Collections.reverseOrder(titleComparator)); System.out.println("sorted list in descending order of title: " + listOfCourses); // sorting arraylist in descending order of fee listOfCourses.sort(Collections.reverseOrder(feeComparator)); System.out.println("sorted list in descending order of fee: " + listOfCourses); } } class Course{ String title; long fee; public Course(String title, long fee){ this.title = title; this.fee = fee; } public String title(){ return title; } public long fee(){ return fee; } @Override public String toString() { return String.format(title + "@ " + fee); } } Output unsorted list: [REST with Spring@ 99, Learn Spring Security@ 110, Introduction to Spring MVC 4@ 0] sorted list in ascending order of title: [Introduction to Spring MVC 4@ 0, Learn Spring Security@ 110, REST with Spring@ 99] sorted list in ascending order of fee: [Introduction to Spring MVC 4@ 0, REST with Spring@ 99, Learn Spring Security@ 110] sorted list in descending order of title: [REST with Spring@ 99, Learn Spring Security@ 110, Introduction to Spring MVC 4@ 0] sorted list in descending order of fee: [Learn Spring Security@ 110, REST with Spring@ 99, Introduction to Spring MVC 4@ 0]
From the output, it's clear that our sorting works as expected. In the ascending order of title, Introduction to Spring MVC 4 comes first because it starts with the letter "I", while the other starts with the letter "L" and letter "R". 

In descending order, the "REST with Spring" comes first because of the same reason. While, in the ascending order of fee, again, Introduction to Spring MVC 4 comes first because it is the least expensive out of these three courses.

That's all about how to sort an ArrayList of Objects using Comparator in Java. You have learned to sort ArrayList in both ascending and descending order using Comparator. As I said, you don't need to create two comparators, instead, you just create a comparator to sort the list of objects based upon any attribute you want and then use the Collections.reverseOrder() method to reverse the order imposed by Comparator. It accepts a comparator and then sorts the elements in the array list in the reverse order of that comparator. This way you can sort the list of objects in descending order.

Further Reading


Top 10 Free Tutorials to Learn Java 8
Top 5 Books to Learn Java 8 and Functional Programming
Difference between Comparator and Comparable in Java
How to sort an array in place in Java? Thanks for reading this article so far. If you like this tutorial then please share it with your friends and colleagues. If you have any questions or feedback or you didn't understand any part of this example then please drop a comment and I'll try to answer your question.