Java Comparator Example

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 1 

Let’s see how to sort a collection of Employee objects by following Employee fields:
  1. Sort employees by Name
  2. Sort employees by Salary
  3. Sort employees by JoiningDate
  4. Sort employees by Name in descending order
  5. Chaining multiple Comparators - Sort by Salary. If Salary is the same then sort by Name
Let's write a Java program to sort employees in ascending order by name, salary, joining date, and sort employees in descending order.
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}]

Comparator interface Example 2

Let's see one more example, sorting person objects by age using Java 8 Lambda expressions and Java 8 forEach() method.
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<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;
    }
}

Reference

Comments