The Differences Between Comparable and Comparator – How to Use Both Effectively
In Java, the Comparable
and Comparator
interfaces are highly useful when it comes to sorting collections of objects. Java provides some built-in methods to sort primitive types and wrapper classes. In this post, you’ll first learn how to sort arrays and lists with primitive types and wrapper classes, and then how to sort custom class objects using the Comparable
and Comparator
interfaces.
Sorting Primitive Arrays and Lists
First, here’s an example of how to sort primitive arrays or arrays of wrapper classes in Java. Below is the code to sort an array of integers and an array of strings:
package com.journaldev.sort; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; public class JavaObjectSorting { public static void main(String[] args) { // Sorting a primitive array (int) int[] intArr = {5, 9, 1, 10}; Arrays.sort(intArr); System.out.println(Arrays.toString(intArr)); // Sorting a string array String[] strArr = {"A", "C", "B", "Z", "E"}; Arrays.sort(strArr); System.out.println(Arrays.toString(strArr)); // Sorting a list of wrapper classes (Strings) List strList = new ArrayList<>(); strList.add("A"); strList.add("C"); strList.add("B"); strList.add("Z"); strList.add("E"); Collections.sort(strList); for (String str : strList) { System.out.print(" " + str); } } }
Output:
[1, 5, 9, 10] [A, B, C, E, Z] A B C E Z
Sorting Custom Class Objects
Sorting arrays of custom class objects requires more effort. Java offers the Comparable
and Comparator
interfaces for this purpose. Here’s an example of how to sort an array of Employee
objects:
package com.journaldev.sort; public class Employee { private int id; private String name; private int age; private long salary; public int getId() { return id; } public String getName() { return name; } public int getAge() { return age; } public long getSalary() { return salary; } public Employee(int id, String name, int age, int salary) { this.id = id; this.name = name; this.age = age; this.salary = salary; } @Override public String toString() { return "[id=" + this.id + ", name=" + this.name + ", age=" + this.age + ", salary=" + this.salary + "]"; } }
Attempting to sort this array directly results in a runtime exception, as Employee
does not implement the Comparable
interface.
Solution with Comparable:
To resolve this, we implement the Comparable
interface and override the compareTo
method to allow sorting Employee
objects by their id
by default:
package com.journaldev.sort; public class Employee implements Comparable { private int id; private String name; private int age; private long salary; @Override public int compareTo(Employee emp) { return this.id - emp.id; } @Override public String toString() { return "[id=" + this.id + ", name=" + this.name + ", age=" + this.age + ", salary=" + this.salary + "]"; } }
After this change, you can now sort the Employee
array:
Employee[] empArr = new Employee[4]; empArr[0] = new Employee(10, "Mikey", 25, 10000); empArr[1] = new Employee(20, "Arun", 29, 20000); empArr[2] = new Employee(5, "Lisa", 35, 5000); empArr[3] = new Employee(1, "Pankaj", 32, 50000); Arrays.sort(empArr); System.out.println("Default Sorting:\n" + Arrays.toString(empArr));
Output:
[id=1, name=Pankaj, age=32, salary=50000], [id=5, name=Lisa, age=35, salary=5000], [id=10, name=Mikey, age=25, salary=10000], [id=20, name=Arun, age=29, salary=20000]
Sorting by Different Criteria with Comparator
While the Comparable
interface only allows for one default sorting criterion, the Comparator
interface enables sorting by multiple criteria. Below are some custom Comparator
implementations that allow sorting employees by Salary
, Age
, or Name
:
import java.util.Comparator; public class Employee { public static Comparator SalaryComparator = new Comparator() { @Override public int compare(Employee e1, Employee e2) { return (int) (e1.getSalary() - e2.getSalary()); } }; public static Comparator AgeComparator = new Comparator() { @Override public int compare(Employee e1, Employee e2) { return e1.getAge() - e2.getAge(); } }; public static Comparator NameComparator = new Comparator() { @Override public int compare(Employee e1, Employee e2) { return e1.getName().compareTo(e2.getName()); } }; }
These comparators can be used to sort the Employee
array by different criteria:
Arrays.sort(empArr, Employee.SalaryComparator); System.out.println("Sorted by Salary:\n" + Arrays.toString(empArr)); Arrays.sort(empArr, Employee.AgeComparator); System.out.println("Sorted by Age:\n" + Arrays.toString(empArr)); Arrays.sort(empArr, Employee.NameComparator); System.out.println("Sorted by Name:\n" + Arrays.toString(empArr));
Conclusion
In Java, the Comparable
and Comparator
interfaces provide a flexible way to sort custom objects. The Comparable
interface defines a fixed default sorting order, which is ideal for cases where a unified sorting method is needed. On the other hand, the Comparator
interface allows sorting by different criteria, making it useful when flexible, situation-dependent sorting is required.
By using Comparator
, you can define as many sorting methods as needed and choose the appropriate criterion—such as salary, age, or name—depending on the context. This flexibility helps meet the varying demands of practical applications.