The Comparator interface is used to sort a collection of objects that can be compared. The object comparison can be made using Comparable interface as well, but it restricts us by comparing objects in a specific single way only. If we want to sort this collection, based on multiple criteria/fields, then we have to use Comparator
only.
Comparator<User> comparator = Comparator.comparing(User::firstName);
Collections.sort(list, comparator);
1. Setup
To demo the concept, we are using the record User
with four attributes. We will use it to understand various use cases.
public record User(Long id, String firstName, String lastName, Integer age) {
}
2. Creating Comparator without Lambda
If we are not using lambda expressions, we can create a Comparator instance using an anonymous inner class. In the following example, we are creating a Comparator instance that compares the two instances of User class by their firstName property.
Comparator<User> byNameComparator = new Comparator<User>() {
@Override
public int compare(User u1, User u2) {
return u1.firstName().compareTo(u2.firstName());
}
};
3. Comparator with Lambda
Lambda expressions are code blocks that take arguments and return a value. They are similar to anonymous methods. We can use the lambda expressions to create Comparator instances in a much short form. For example, we can rewrite the previous byNameComparator as follows:
Comparator<User> firstNameComparator = (User u1, User u2) -> u1.firstName().compareTo(u2.firstName());
Lambda expressions allow omitting the type definitions. The compiler infers the types by the variable type.
Comparator<User> firstNameComparator = (u1, u2) -> u1.firstName().compareTo(u2.firstName());
We can further simplify the expression by using the method reference as follows:
Comparator<User> firstNameComparator = Comparator.comparing(User::firstName);
4. Reverse Comparator
What if we want to sort the list by first name but in reversed order. It’s really very easy; use Comparator.reversed() method.
Comparator<User> firstNameComparator = Comparator.comparing(User::firstName);
Comparator<User> reverseComparator = firstNameComparator.reverse();
5. Chaining Comparators
Here we are sorting the list of employees first by their first name, then by their last name. Just as we apply to sort SQL statements. Now we don’t always need to use sorting on multiple fields in SQL select statements, we can sort them in java as well.
Comparator<User> fullNameComparator = Comparator.comparing(User::firstName).thenComparing(User::lastName);
6. Parallel Sort
We can sort the collection of objects in parallel using multiple threads as well. It will be very fast if the collection is big enough to have thousands of objects. For a small collection of objects, normal sorting is good enough and recommended.
Comparator<User> firstNameComparator = Comparator.comparing(User::firstName);
Arrays.parallelSort(usersArray, firstNameComparator);
That’s all for using lambda with Comparator
to sort objects. Please share with all of us if you know more techniques around this concept.
Happy Learning !!