Comparator is used when we want to sort a collection of objects which can be compared with each other. This comparison can be done using Comparable
interface as well, but it restrict you compare these objects in a single particular way only. If you want to sort this collection, based on multiple criterias/fields, then you have to use Comparator
only.
Quick Reference:
//Compare by Id Comparator<Employee> compareById_1 = Comparator.comparing(e -> e.getId()); Comparator<Employee> compareById_2 = (Employee o1, Employee o2) -> o1.getId().compareTo( o2.getId() ); //Compare by firstname Comparator<Employee> compareByFirstName = Comparator.comparing(e -> e.getFirstName()); //how to use comparator Collections.sort(employees, compareById);
1) Overview
To demo the concept, I am using class Employee
with four attributes. We will use it to understand various use cases.
public class Employee { private Integer id; private String firstName; private String lastName; private Integer age; public Employee(Integer id, String firstName, String lastName, Integer age){ this.id = id; this.firstName = firstName; this.lastName = lastName; this.age = age; } //Other getter and setter methods @Override public String toString() { return "\n["+this.id+","+this.firstName+","+this.lastName+","+this.age+"]"; } }
Additionally, I have written one method which always returns a list of Employees
in unsorted order.
private static List<Employee> getEmployees(){ List<Employee> employees = new ArrayList<>(); employees.add(new Employee(6,"Yash", "Chopra", 25)); employees.add(new Employee(2,"Aman", "Sharma", 28)); employees.add(new Employee(3,"Aakash", "Yaadav", 52)); employees.add(new Employee(5,"David", "Kameron", 19)); employees.add(new Employee(4,"James", "Hedge", 72)); employees.add(new Employee(8,"Balaji", "Subbu", 88)); employees.add(new Employee(7,"Karan", "Johar", 59)); employees.add(new Employee(1,"Lokesh", "Gupta", 32)); employees.add(new Employee(9,"Vishu", "Bissi", 33)); employees.add(new Employee(10,"Lokesh", "Ramachandran", 60)); return employees; }
2) Sort by first name
Basic usecase where a list of employees will be sorted based on their first name.
List<Employee> employees = getEmployees(); //Sort all employees by first name employees.sort(Comparator.comparing(e -> e.getFirstName())); //OR you can use below employees.sort(Comparator.comparing(Employee::getFirstName)); //Let's print the sorted list System.out.println(employees); Output: //Names are sorted by first name [ [3,Aakash,Yaadav,52], [2,Aman,Sharma,28], [8,Balaji,Subbu,88], [5,David,Kameron,19], [4,James,Hedge,72], [7,Karan,Johar,59], [1,Lokesh,Gupta,32], [10,Lokesh,Ramachandran,60], [9,Vishu,Bissi,33], [6,Yash,Chopra,25] ]
3) Sort by first name – ‘reverse order’
What if we want to sort on the first name but in revered order. It’s really very easy; use reversed()
method.
List<Employee> employees = getEmployees(); //Sort all employees by first name; And then reversed Comparator<Employee> comparator = Comparator.comparing(e -> e.getFirstName()); employees.sort(comparator.reversed()); //Let's print the sorted list System.out.println(employees); Output: //Names are sorted by first name [[6,Yash,Chopra,25], [9,Vishu,Bissi,33], [1,Lokesh,Gupta,32], [10,Lokesh,Ramachandran,60], [7,Karan,Johar,59], [4,James,Hedge,72], [5,David,Kameron,19], [8,Balaji,Subbu,88], [2,Aman,Sharma,28], [3,Aakash,Yaadav,52]]
4) Sort by last name
We can use a similar code to sort on last name as well.
List<Employee> employees = getEmployees(); //Sort all employees by first name employees.sort(Comparator.comparing(e -> e.getLastName())); //OR you can use below employees.sort(Comparator.comparing(Employee::getLastName)); //Let's print the sorted list System.out.println(employees); Output: //Names are sorted by first name [[9,Vishu,Bissi,33], [6,Yash,Chopra,25], [1,Lokesh,Gupta,32], [4,James,Hedge,72], [7,Karan,Johar,59], [5,David,Kameron,19], [10,Lokesh,Ramachandran,60], [2,Aman,Sharma,28], [8,Balaji,Subbu,88], [3,Aakash,Yaadav,52]]
5) Sort on multiple fields – thenComparing()
Here we are sorting the list of employees first by their first name, and then sort again the list of last name. Just as we apply sorting on SQL statements. It’s actually a very good feature.
Now you don’t need to always use sorting on multiple fields in SQL select statements, you can sort them in java as well.
List<Employee> employees = getEmployees(); //Sorting on multiple fields; Group by. Comparator<Employee> groupByComparator = Comparator.comparing(Employee::getFirstName) .thenComparing(Employee::getLastName); employees.sort(groupByComparator); System.out.println(employees); Output: [3,Aakash,Yaadav,52], [2,Aman,Sharma,28], [8,Balaji,Subbu,88], [5,David,Kameron,19], [4,James,Hedge,72], [7,Karan,Johar,59], [1,Lokesh,Gupta,32], //These both employees are [10,Lokesh,Ramachandran,60], //sorted on last name as well [9,Vishu,Bissi,33], [6,Yash,Chopra,25]
5) Parallel sort (with multiple threads)
You can sort the collection of objects in parallel using multiple threads as well. It is going to 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.
//Parallel Sorting Employee[] employeesArray = employees.toArray(new Employee[employees.size()]); //Parallel sorting Arrays.parallelSort(employeesArray, groupByComparator); System.out.println(employeesArray); Output: [3,Aakash,Yaadav,52], [2,Aman,Sharma,28], [8,Balaji,Subbu,88], [5,David,Kameron,19], [4,James,Hedge,72], [7,Karan,Johar,59], [1,Lokesh,Gupta,32], //These both employees are [10,Lokesh,Ramachandran,60], //sorted on last name as well [9,Vishu,Bissi,33], [6,Yash,Chopra,25]
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 !!
Leave a Reply