Wednesday, February 15, 2023

How to Sort ArrayList of Objects by Fields in Java? Custom + Reversed Order Sorting Comparator Example

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.



How to Sort an ArrayList of Objects by Fields or Properties using Comparator 

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.

ArrayList Custom and Reversed Order Sorting in Java? Comparator Example




Java Program to Sort an ArrayList of Objects by Fields using Comparator

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.

Java Program to sort an ArrayList using Comparator

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?
How to sort List of object on multiple fields

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.

1 comment:

  1. How can we sort a List of object by property1 ascending then property 2 descending?

    ReplyDelete

Feel free to comment, ask questions if you have any doubt.