Guide to Comparator Interface

The Comparable interface that we learned in the previous guide defines a default ordering for the objects of a class. This default ordering is also called the natural ordering of the objects.
What if you want to sort some objects in an order other than their natural ordering? Or what if you want to sort some objects that don't implement Comparable? To do either of these things, you'll need to provide a Comparator — an object that encapsulates an ordering. Like the Comparable interface, the Comparator interface consists of a single method.
public interface Comparator<T> {
    int compare(T o1, T o2);
}
The implementation of the compare() method should return
  • a negative integer, if the first argument is less than the second,
  • zero, if the first argument is equal to the second, and
  • a positive integer, if the first argument is greater than the second.
If either of the arguments has an inappropriate type for the Comparator, the compare method throws a ClassCastException.

Comparator interface Example

Let’s see how to sort a collection of Employee objects that we defined in the previous section based on different fields by defining different Comparators.

Example 1: Sort employees by Name

List<Employee> employees = new ArrayList<>();

employees.add(new Employee(1010, "Rajeev", 100000.00, LocalDate.of(2010, 7, 10)));
employees.add(new Employee(1004, "Chris", 95000.50, LocalDate.of(2017, 3, 19)));
employees.add(new Employee(1015, "David", 134000.00, LocalDate.of(2017, 9, 28)));
employees.add(new Employee(1009, "Steve", 100000.00, LocalDate.of(2016, 5, 18)));

System.out.println("Employees : " + employees);

// Sort employees by Name
Collections.sort(employees, Comparator.comparing(Employee::getName));
System.out.println("\nEmployees (Sorted by Name) : " + employees);

Example 2: Sort employees by Salary

List<Employee> employees = new ArrayList<>();

employees.add(new Employee(1010, "Rajeev", 100000.00, LocalDate.of(2010, 7, 10)));
employees.add(new Employee(1004, "Chris", 95000.50, LocalDate.of(2017, 3, 19)));
employees.add(new Employee(1015, "David", 134000.00, LocalDate.of(2017, 9, 28)));
employees.add(new Employee(1009, "Steve", 100000.00, LocalDate.of(2016, 5, 18)));

// Sort employees by Salary
Collections.sort(employees, Comparator.comparingDouble(Employee::getSalary));
System.out.println("\nEmployees (Sorted by Salary) : " + employees);

Example 3: Sort employees by JoiningDate

List<Employee> employees = new ArrayList<>();

employees.add(new Employee(1010, "Rajeev", 100000.00, LocalDate.of(2010, 7, 10)));
employees.add(new Employee(1004, "Chris", 95000.50, LocalDate.of(2017, 3, 19)));
employees.add(new Employee(1015, "David", 134000.00, LocalDate.of(2017, 9, 28)));
employees.add(new Employee(1009, "Steve", 100000.00, LocalDate.of(2016, 5, 18)));

// Sort employees by JoiningDate
Collections.sort(employees, Comparator.comparing(Employee::getJoiningDate));
System.out.println("\nEmployees (Sorted by JoiningDate) : " + employees);

Example 4: Sort employees by Name in descending order

List<Employee> employees = new ArrayList<>();

employees.add(new Employee(1010, "Rajeev", 100000.00, LocalDate.of(2010, 7, 10)));
employees.add(new Employee(1004, "Chris", 95000.50, LocalDate.of(2017, 3, 19)));
employees.add(new Employee(1015, "David", 134000.00, LocalDate.of(2017, 9, 28)));
employees.add(new Employee(1009, "Steve", 100000.00, LocalDate.of(2016, 5, 18)));

// Sort employees by Name in descending order
Collections.sort(employees, Comparator.comparing(Employee::getName).reversed());
System.out.println("\nEmployees (Sorted by Name in descending order) : " + employees);

Example 5: Chaining multiple Comparators

List<Employee> employees = new ArrayList<>();

employees.add(new Employee(1010, "Rajeev", 100000.00, LocalDate.of(2010, 7, 10)));
employees.add(new Employee(1004, "Chris", 95000.50, LocalDate.of(2017, 3, 19)));
employees.add(new Employee(1015, "David", 134000.00, LocalDate.of(2017, 9, 28)));
employees.add(new Employee(1009, "Steve", 100000.00, LocalDate.of(2016, 5, 18)));

// Chaining multiple Comparators
// Sort by Salary. If Salary is same then sort by Name
Collections.sort(employees, Comparator.comparingDouble(Employee::getSalary)
                            .thenComparing(Employee::getName));
System.out.println("\nEmployees (Sorted by Salary and Name) : " + employees);

Complete Example for Reference

import java.time.LocalDate;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class ComparatorExample {
    public static void main(String[] args) {
        List<Employee> employees = new ArrayList<>();

        employees.add(new Employee(1010, "Rajeev", 100000.00, LocalDate.of(2010, 7, 10)));
        employees.add(new Employee(1004, "Chris", 95000.50, LocalDate.of(2017, 3, 19)));
        employees.add(new Employee(1015, "David", 134000.00, LocalDate.of(2017, 9, 28)));
        employees.add(new Employee(1009, "Steve", 100000.00, LocalDate.of(2016, 5, 18)));

        System.out.println("Employees : " + employees);

        // Sort employees by Name
        Collections.sort(employees, Comparator.comparing(Employee::getName));
        System.out.println("\nEmployees (Sorted by Name) : " + employees);

        // Sort employees by Salary
        Collections.sort(employees, Comparator.comparingDouble(Employee::getSalary));
        System.out.println("\nEmployees (Sorted by Salary) : " + employees);

        // Sort employees by JoiningDate
        Collections.sort(employees, Comparator.comparing(Employee::getJoiningDate));
        System.out.println("\nEmployees (Sorted by JoiningDate) : " + employees);

        // Sort employees by Name in descending order
        Collections.sort(employees, Comparator.comparing(Employee::getName).reversed());
        System.out.println("\nEmployees (Sorted by Name in descending order) : " + employees);

        // Chaining multiple Comparators
        // Sort by Salary. If Salary is same then sort by Name
        Collections.sort(employees, Comparator.comparingDouble(Employee::getSalary)
                                    .thenComparing(Employee::getName));
        System.out.println("\nEmployees (Sorted by Salary and Name) : " + employees);
    }
}
Output:
Employees : [Employee{id=1010, name='Rajeev', salary=100000.0, joiningDate=2010-07-10},
Employee{id=1004, name='Chris', salary=95000.5, joiningDate=2017-03-19}, 
Employee{id=1015, name='David', salary=134000.0, joiningDate=2017-09-28},
Employee{id=1009, name='Steve', salary=100000.0, joiningDate=2016-05-18}]

Employees (Sorted by Name) : 
[Employee{id=1004, name='Chris', salary=95000.5, joiningDate=2017-03-19},
 Employee{id=1015, name='David', salary=134000.0, joiningDate=2017-09-28}, 
Employee{id=1010, name='Rajeev', salary=100000.0, joiningDate=2010-07-10},
 Employee{id=1009, name='Steve', salary=100000.0, joiningDate=2016-05-18}]

Employees (Sorted by Salary) : 
[Employee{id=1004, name='Chris', salary=95000.5, joiningDate=2017-03-19}, 
Employee{id=1010, name='Rajeev', salary=100000.0, joiningDate=2010-07-10},
 Employee{id=1009, name='Steve', salary=100000.0, joiningDate=2016-05-18}, 
Employee{id=1015, name='David', salary=134000.0, joiningDate=2017-09-28}]

Employees (Sorted by JoiningDate) : 
[Employee{id=1010, name='Rajeev', salary=100000.0, joiningDate=2010-07-10}, 
Employee{id=1009, name='Steve', salary=100000.0, joiningDate=2016-05-18},
 Employee{id=1004, name='Chris', salary=95000.5, joiningDate=2017-03-19}, 
Employee{id=1015, name='David', salary=134000.0, joiningDate=2017-09-28}]

Employees (Sorted by Name in descending order) : 
[Employee{id=1009, name='Steve', salary=100000.0, joiningDate=2016-05-18},
 Employee{id=1010, name='Rajeev', salary=100000.0, joiningDate=2010-07-10},
 Employee{id=1015, name='David', salary=134000.0, joiningDate=2017-09-28}, 
Employee{id=1004, name='Chris', salary=95000.5, joiningDate=2017-03-19}]

Employees (Sorted by Salary and Name) : 
[Employee{id=1004, name='Chris', salary=95000.5, joiningDate=2017-03-19},
 Employee{id=1010, name='Rajeev', salary=100000.0, joiningDate=2010-07-10},
 Employee{id=1009, name='Steve', salary=100000.0, joiningDate=2016-05-18}, 
Employee{id=1015, name='David', salary=134000.0, joiningDate=2017-09-28}]

More Examples

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class JLEComparatorExample {

 public static void main(String[] args) {

  List<Person> listOfPerson = new ArrayList<Person>();
  listOfPerson.add(new Person("abc", 27));
  listOfPerson.add(new Person("mno", 26));
  listOfPerson.add(new Person("pqr", 28));
  listOfPerson.add(new Person("xyz", 27));

  // Without lambda expression.
  // Sort list by age
  Comparator<Person> comparator = new Comparator<Person>() {
   @Override
   public int compare(Person o1, Person o2) {
    return o1.getAge() - o2.getAge();
   }
  };

  Collections.sort(listOfPerson, comparator);

  System.out.println(" sort persons by age in ascending order");
  for (Person person : listOfPerson) {
   System.out.println(" Person name : " + person.getName());
  }

  // Witht lambda expression.
  // Sort list by age

  Collections.sort(listOfPerson, (Person o1, Person o2) -> {
   return o1.getAge() - o2.getAge();
  });
  // Use forEach method added in java 8
  System.out.println(" sort persons by age in ascending order");
  listOfPerson.forEach(
         (person) -> System.out.println(" Person name : " + person.getName()));
 }
}

class Person {
 private String name;
 private int age;

 public Person(String name, int age) {
  super();
  this.name = name;
  this.age = age;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public int getAge() {
  return age;
 }

 public void setAge(int age) {
  this.age = age;
 }
}

Related Collections Framework API Guides


Free Spring Boot Tutorial | Full In-depth Course | Learn Spring Boot in 10 Hours


Watch this course on YouTube at Spring Boot Tutorial | Fee 10 Hours Full Course