Understanding the Comparator Interface in Java 8
Published: February 22, 2016
Introduction
Java 8 introduced many new features that make working with collections more powerful and efficient. One of these features is the Comparator
interface, which allows developers to sort objects in a collection based on specific criteria.
In this tutorial, we’ll cover:
- What the
Comparator
interface is and why it’s useful. - How to implement and use a comparator to sort objects in Java.
- How to use the new sorting methods introduced in Java 8.
What is a Comparator?
A Comparator
is an interface in the java.util
package that provides a way to define custom sorting logic for objects in a collection. The interface has two main methods:
- compare(T o1, T o2) – Compares two objects of the same type.
- reversed() – Returns a comparator that imposes the reverse order of the original comparator.
Before Java 8, sorting was often done by implementing the Comparable
interface in the objects you wanted to sort. However, using Comparator
allows you to sort objects based on external criteria, without modifying the original class.
Using the Comparator Interface
Let’s look at an example where we have a list of Employee
objects, and we want to sort them by their salary and name.
Creating the Employee Class
public class Employee {
private String name;
private double salary;
public Employee(String name, double salary) {
this.name = name;
this.salary = salary;
}
public String getName() {
return name;
}
public double getSalary() {
return salary;
}
@Override
public String toString() {
return "Employee{name='" + name + "', salary=" + salary + '}';
}
}
Sorting Using a Comparator
We will now sort a list of Employee
objects based on their salary and name. First, let’s create a Comparator
to sort by salary.
import java.util.*;
public class ComparatorExample {
public static void main(String[] args) {
List<Employee> employees = Arrays.asList(
new Employee("Alice", 50000),
new Employee("Bob", 60000),
new Employee("Charlie", 45000)
);
// Sorting by salary using Comparator
Comparator<Employee> salaryComparator = Comparator.comparingDouble(Employee::getSalary);
employees.sort(salaryComparator);
System.out.println("Employees sorted by salary:");
for (Employee employee : employees) {
System.out.println(employee);
}
}
}
Output:
Employees sorted by salary:
Employee{name='Charlie', salary=45000.0}
Employee{name='Alice', salary=50000.0}
Employee{name='Bob', salary=60000.0}
In the example above, we used Comparator.comparingDouble()
to sort employees based on their salary in ascending order.
Sorting by Multiple Criteria
You can also chain multiple Comparator
instances to perform multi-level sorting. For example, let’s sort by salary first and then by name.
Comparator<Employee> multiCriteriaComparator = Comparator
.comparingDouble(Employee::getSalary)
.thenComparing(Employee::getName);
employees.sort(multiCriteriaComparator);
System.out.println("Employees sorted by salary and name:");
for (Employee employee : employees) {
System.out.println(employee);
}
Output:
Employees sorted by salary and name:
Employee{name='Charlie', salary=45000.0}
Employee{name='Alice', salary=50000.0}
Employee{name='Bob', salary=60000.0}
In this case, employees are first sorted by salary. If two employees have the same salary, they are sorted by name.
Using Lambda Expressions with Comparator
In Java 8, you can use lambda expressions to simplify the implementation of comparators. This makes the code more concise and readable.
Sorting by Salary Using Lambda Expression
Comparator<Employee> salaryComparatorLambda = (e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary());
employees.sort(salaryComparatorLambda);
System.out.println("Employees sorted by salary (Lambda):");
for (Employee employee : employees) {
System.out.println(employee);
}
Output:
Employees sorted by salary (Lambda):
Employee{name='Charlie', salary=45000.0}
Employee{name='Alice', salary=50000.0}
Employee{name='Bob', salary=60000.0}
As you can see, the lambda expression makes the comparator much more concise.
Reversed Sorting
Java 8 also allows you to easily reverse the order of a comparator using the reversed()
method.
Comparator<Employee> reversedComparator = salaryComparator.reversed();
employees.sort(reversedComparator);
System.out.println("Employees sorted by salary (reversed):");
for (Employee employee : employees) {
System.out.println(employee);
}
Output:
Employees sorted by salary (reversed):
Employee{name='Bob', salary=60000.0}
Employee{name='Alice', salary=50000.0}
Employee{name='Charlie', salary=45000.0}
Using Comparator with Collections.sort()
Instead of using employees.sort(comparator)
, you can also use Collections.sort()
:
Collections.sort(employees, salaryComparator);
This will sort the employees
list using the provided comparator.
Conclusion
The Comparator
interface is a powerful tool for sorting collections in Java 8. It provides flexible ways to define custom sorting logic for objects, allowing you to easily sort by one or more criteria, use lambda expressions, reverse the order, and much more.
In the next tutorial, we will explore The forEach() Method in Java 8, and how it simplifies iteration over collections.