Comparable Java Example
In this tutorial, we will discuss Java comparable objects. Java provides the Comparator interface and the Comparable
interface, which contains only one method, called compareTo
. This method compares two objects, to impose an order between them. Specifically, it returns a negative integer, zero, or a positive integer to indicate that the input object is less than, equal to or greater than the existing object.
1. The Comparable Interface
Java provides the Comparator interface, which contains two methods, called compare
and equals
. The first method compares its two input arguments and imposes an order between them. It returns a negative integer, zero, or a positive integer to indicate that the first argument is less than, equal to, or greater than the second. The second method requires an Object
as a parameter and aims to decide whether the input object is equal to the comparator. The method returns true, only if the specified object is also a comparator and it imposes the same ordering as the comparator.
The Java Comparable interface is mainly used to sort the arrays or lists of custom objects. Lists and arrays of objects that implement the Java Comparable interface can be sorted automatically by Collections.sort()
and Arrays.sort()
.
Let’s see how we can sort elements of arrays and lists containing wrapper classes objects that already implements the Java Comparable interface.
Sorting arrays and lists with warpper class elements
//Sorting array of integers using Arrays.sort() int[] arr = {8, 5, 1, 4, 7, 9, 2, 3, 6, 0}; System.out.println("Integer array before sorting: " + Arrays.toString(arr)); Arrays.sort(arr); System.out.println("Integer array after sorting: " + Arrays.toString(arr)); //Sorting array of Strings using Arrays.sort() String[] names = {"Pat", "Lesa", "Jackie", "Charles"}; System.out.println("String array before sorting: " + Arrays.toString(names)); Arrays.sort(names); System.out.println("String array after sorting: " + Arrays.toString(names)); //Sorting List of String Collections.sort() List<String> fruits = Arrays.asList("Orange", "Banana", "Apple", "Guava", "Grapes"); System.out.println("String list before sorting: " + fruits); Collections.sort(fruits); System.out.println("String list after sorting: " + fruits);
output
Integer array before sorting: [8, 5, 1, 4, 7, 9, 2, 3, 6, 0] Integer array after sorting: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] String array before sorting: [Pat, Lesa, Jackie, Charles] String array after sorting: [Charles, Jackie, Lesa, Pat] String list before sorting: [Orange, Banana, Apple, Guava, Grapes] String list after sorting: [Apple, Banana, Grapes, Guava, Orange]
Since all wrapper classes already implement the Java Comparable Interface and provided a default implementation of compareTo()
the method, that is why we can use Collections.sort()
and Arrays.sort()
on these objects.
If we wanted to sort a user-defined class let’s say Employee
class into some specific order we have to implement the Comparable
interface and provide the implementation of its compareTo()
method. Comparable
interface present into java.lang
package. By using the Comparable
interface we can define only one way to sort element of Arrays or List containing the user-defined class.
1.1 The compareTo() of Comparable Interface in Java
This method compares the current object and the object which has been passed and returns-
- A positive integer, if the current object is greater than the specified object.
- A negative integer, if the current object is less than the specified object.
- Zero, if the current object is equal to the specified object.
The declaration of compareTo()
looks like below in Comparable
interface-
int compareTo(T o)
The above method also throws NullPointerException or ClassCastException
if the specified object is null
or if the specified object’s type prevents it from being compared to this object.
Now let’s use Comparable
one our defined Employee
class and provide the implementation of compareTo()
method to sort its elements based on their first name.
The Employee class
class Employee implements Comparable { private int id; private String name; private Double salary; public Employee(int id, String name, Double salary) { this.id = id; this.name = name; this.salary = salary; } @Override public int compareTo(Employee employee) { return this.name.compareTo(employee.name); } @Override public String toString() { return "Employee{" + "id=" + id + ", name='" + name + '\'' + ", salary=" + salary + '}'; } }
Now, let’s use this Employee class with array and list to sort them-
Sorting Employee elements
//Sorting array of Employee objects using Arrays.sort() Employee[] employees = {new Employee(1, "Pat", 1000.0), new Employee(2, "Lesa", 2500.0), new Employee(3, "Jackie", 1500.0), new Employee(4, "Charles", 6000.0)}; System.out.println("Employee array before sorting: " + Arrays.toString(employees)); Arrays.sort(employees); System.out.println("Employee array after sorting: " + Arrays.toString(employees)); //Sorting List of Employee objects Collections.sort() List employeeList = Arrays.asList(new Employee(1, "Pat", 1000.0), new Employee(2, "Lesa", 2500.0), new Employee(3, "Jackie", 1500.0), new Employee(4, "Charles", 6000.0)); System.out.println("Employee list before sorting: " + employeeList); Arrays.sort(employees); System.out.println("Employee list after sorting: " + employeeList);
Here in this code, first we created an array of Employee
objects and then sorted them using Arrays.sort()
method. Again we created a list of same employee objects and used Collections.sort() to sort them. Finally, here is the output-
Output
Employee array before sorting: [Employee{id=1, name='Pat', salary=1000.0}, Employee{id=2, name='Lesa', salary=2500.0}, Employee{id=3, name='Jackie', salary=1500.0}, Employee{id=4, name='Charles', salary=6000.0}] Employee array after sorting: [Employee{id=4, name='Charles', salary=6000.0}, Employee{id=3, name='Jackie', salary=1500.0}, Employee{id=2, name='Lesa', salary=2500.0}, Employee{id=1, name='Pat', salary=1000.0}] Employee list before sorting: [Employee{id=1, name='Pat', salary=1000.0}, Employee{id=2, name='Lesa', salary=2500.0}, Employee{id=3, name='Jackie', salary=1500.0}, Employee{id=4, name='Charles', salary=6000.0}] Employee list after sorting: [Employee{id=1, name='Pat', salary=1000.0}, Employee{id=2, name='Lesa', salary=2500.0}, Employee{id=3, name='Jackie', salary=1500.0}, Employee{id=4, name='Charles', salary=6000.0}]
2. The Comparator Java Interface
One of the limitations of sorting using Comparable interface is that it gives only one way to sort the elements of arrays or collections. If we wanted to have multiple choices Comparable interface doesn’t give a way to do this.
If we wanted to have multiple choices for sorting a given collection or array element, we would have to write multiple Comparator Java classes implementing Comparator
interface and providing an implementation of it compare()
method. We can pass a comparator Java class as the second argument to Collections.sort()
and Arrays.sort()
to use respective sorting logic.
2.1 The compare() of Comparator Interface in Java
This method compares the first object with the object and returns-
- A positive integer, if the current object is greater than the specified object.
- A negative integer, if the current object is less than the specified object.
- Zero, if the current object is equal to the specified object.
The declaration of compare()
looks like below in Comparator
interface-
int compare(T o1, T o2)
The above method also throws NullPointerException or ClassCastException
if the specified object is null
or if the specified object’s type prevents it from being compared to this object.
Now, let’s write Comparator for the same Employee
class to sort it by using name and salary. We will write EmployeeNameComparator
and EmployeeSalaryComparator
to do the sorting. Now let’s write the two comparator classes-
EmployeeNameComparator.java
package com.javacodegeeks.examples.comparable; import java.util.Comparator; class EmployeeNameComparator implements Comparator<Employee> { @Override public int compare(Employee e1, Employee e2) { return e1.getName().compareTo(e2.getName()); } }
EmployeeSalaryComparator.java
package com.javacodegeeks.examples.comparable; import java.util.Comparator; public class EmployeeSalaryComparator implements Comparator<Employee> { @Override public int compare(Employee e1, Employee e2) { return e1.getSalary().compareTo(e2.getSalary()); } }
Now, let’s use these comparators in our code to sort Employee array and list based on name and salary-
Using EmployeeNameComparator with Employee objects
//Sorting array of Employee objects by their name using Arrays.sort() Employee[] employees = {new Employee(1, "Pat", 1000.0), new Employee(2, "Lesa", 2500.0), new Employee(3, "Jackie", 1500.0), new Employee(4, "Charles", 6000.0)}; System.out.println("Employee array before sorting: " + Arrays.toString(employees)); Arrays.sort(employees, new EmployeeNameComparator()); System.out.println("Employee array after sorting by name: " + Arrays.toString(employees)); //Sorting List of Employee objects by their name Collections.sort() List employeeList = Arrays.asList(new Employee(1, "Pat", 1000.0), new Employee(2, "Lesa", 2500.0), new Employee(3, "Jackie", 1500.0), new Employee(4, "Charles", 6000.0)); System.out.println("Employee list before sorting: " + employeeList); Collections.sort(employeeList, new EmployeeNameComparator()); System.out.println("Employee list after sorting by name: " + employeeList);
In the above code, we used EmployeeNameComparator
to sort Employee array and employee list based on their names. Here is the output of above code.
Output
Employee array before sorting: [Employee{id=1, name='Pat', salary=1000.0}, Employee{id=2, name='Lesa', salary=2500.0}, Employee{id=3, name='Jackie', salary=1500.0}, Employee{id=4, name='Charles', salary=6000.0}] Employee array after sorting by name: [Employee{id=4, name='Charles', salary=6000.0}, Employee{id=3, name='Jackie', salary=1500.0}, Employee{id=2, name='Lesa', salary=2500.0}, Employee{id=1, name='Pat', salary=1000.0}] Employee list before sorting: [Employee{id=1, name='Pat', salary=1000.0}, Employee{id=2, name='Lesa', salary=2500.0}, Employee{id=3, name='Jackie', salary=1500.0}, Employee{id=4, name='Charles', salary=6000.0}] Employee list after sorting by name: [Employee{id=4, name='Charles', salary=6000.0}, Employee{id=3, name='Jackie', salary=1500.0}, Employee{id=2, name='Lesa', salary=2500.0}, Employee{id=1, name='Pat', salary=1000.0}]
Now, let’s use EmployeeSalaryComparator
with Employee objects.
Using EmployeeSalaryComparator with Employee objects
//Sorting array of Employee objects by their salary using Arrays.sort() Employee[] employees = {new Employee(1, "Pat", 1000.0), new Employee(2, "Lesa", 2500.0), new Employee(3, "Jackie", 1500.0), new Employee(4, "Charles", 6000.0)}; System.out.println("Employee array before sorting: " + Arrays.toString(employees)); Arrays.sort(employees, new EmployeeSalaryComparator()); System.out.println("Employee array after sorting by salary: " + Arrays.toString(employees)); //Sorting List of Employee objects by their salary Collections.sort() List employeeList = Arrays.asList(new Employee(1, "Pat", 1000.0), new Employee(2, "Lesa", 2500.0), new Employee(3, "Jackie", 1500.0), new Employee(4, "Charles", 6000.0)); System.out.println("Employee list before sorting: " + employeeList); Collections.sort(employeeList, new EmployeeSalaryComparator()); System.out.println("Employee list after sorting by salary: " + employeeList);
In the above code, we used EmployeeSalaryComparator
to sort Employee array and employee list based on their salary. Here is the output of above code.
Output
Employee array before sorting: [Employee{id=1, name='Pat', salary=1000.0}, Employee{id=2, name='Lesa', salary=2500.0}, Employee{id=3, name='Jackie', salary=1500.0}, Employee{id=4, name='Charles', salary=6000.0}] Employee array after sorting by salary: [Employee{id=1, name='Pat', salary=1000.0}, Employee{id=3, name='Jackie', salary=1500.0}, Employee{id=2, name='Lesa', salary=2500.0}, Employee{id=4, name='Charles', salary=6000.0}] Employee list before sorting: [Employee{id=1, name='Pat', salary=1000.0}, Employee{id=2, name='Lesa', salary=2500.0}, Employee{id=3, name='Jackie', salary=1500.0}, Employee{id=4, name='Charles', salary=6000.0}] Employee list after sorting by salary: [Employee{id=1, name='Pat', salary=1000.0}, Employee{id=3, name='Jackie', salary=1500.0}, Employee{id=2, name='Lesa', salary=2500.0}, Employee{id=4, name='Charles', salary=6000.0}]
3. Difference between Comparable and Comparator Interfaces
Below table shows a comparison between implementing sorting logic by using Comparable and Comparator interfaces-
Property | Comparable | Comparator |
Sort Order | Comparable provides a single sorting order. In other words, we can sort the collection by using only one logic also called default or natural sorting order | The Comparator provides multiple sorting order. In other words, we can sort the collection by using multiple logic passed at run time. It is also known as custom sorting order. |
Modify Classes | To implement Comparable we have to change the existing class on which we have to implement sorting logic | To implement Comparator we don’t require any change to existing class on which we have to implement sorting logic |
Method to implement | It provides the compareTo() method with one argument to sort elements of array or collections. | It provides the compare() method with two arguments to sort elements of array or collections. |
Logical Difference | Logically, Comparable is meant for objects with natural ordering which means the object itself must know how it is to be ordered. | Comparator is meant for objects with custom order which means the object never knows how it is to be ordered. |
Objects needed for Comparision | Comparable interface compares current reference with the object passed in argument. | Comparator interface compares two different objects passed as arguments. |
Method to use | We can sort the list elements of Comparable type by Collections.sort(List) method. | We can sort the list elements of Comparator type by Collections.sort(List, Comparator) method. |
package | Comparable interface is in java.lang package | Comparable interface is in java.util package |
4. When to use Comparable and Comparator
1. We should use the Comparable interface if a default way of sorting Object already exists during the development of the class. For Example, String class objects should be sorted alphabetically and Employee class objects should be sorted by their ids. On the other hand, we should use the Comparator interface if an object can be sorted in multiple ways. For example, The Employee class object can be sorted by its name or salary.
2. Sometimes we are not able to write to the original class or we don’t have access to it. In these situations, since we can’t implement Comparable, Comparator is the only way to sort those objects.
3. If we want the object to be stored in SortedSet
or SortedMap
like TreeSet
and TreeMap
and it doesn’t implement Comparable then before putting them into SortedMap or TreeMap, we should always provide the corresponding Comparator which provides sorting logic.
4. We should not ignore the order of comparison while implementing Comparable or Comparator interface. For example, if we are sorting an object based on the name, we can compare the first name or last name in any order. So decide carefully.
5. The comparator has the advantage of being self-descriptive. For example, if we are writing a Comparator to compare two Employees by their salaries then we could name that comparator SalaryComparator.On the other hand, compareTo() doesn’t have any specific way to indicate its sorting criteria.
5. Conclusion
So in summary, if you want to sort objects based on natural order with one sorting logic then use Comparable in Java. If you want to sort on some custom logic with more than one sorting criterion then go for Comparator in Java.
6. Download the Source Code
That was all about Java Comparable example. Hope you enjoyed it.
You can download the full source code of this example here: Comparable Java Example
Last updated on Aug. 27, 2019
In the above example when you have implemented comparable you didn’t give what type this comparable will be so the code will give compile time error.As, when you will see the implementation of comparable in java you will find it is a generic interface that means when we implement comparable we have to genrify it with the person class.
like this:-
class Person implements Comparable
and not like this
class Person implements Comparable