Comparable and Comparator in Java
Learn via video course
Overview
We all are familiar with sorting data of primitive data types like int, String, char, etc. We can pass the array to the Arrays.sort() method directly, and Java takes care of sorting those values because Java is aware of how to sort numbers, characters, or strings.
But what about the custom objects we create like Student, Employee and so on. Java is unaware of how to sort these custom objects, and we need to provide the logic to sort these custom objects explicitly.
Java provides two interfaces, Comparable and Comparator, that can be used to sort custom objects and objects based on multiple data members.
Introduction to Comparable and Comparator in Java
Comparable and Comparator, it is clear from the name that these are used to compare things. In Java, it may be a value or an object.
But how does it differ from each other? This article will explain the working of Comparable and Comparator in Java with a real-time example.
Consider building a REST API(API is responsible for the communication between computer systems) that returns the list of superheroes from the server. Below are the use cases we need.
-
GET /superheroes Returns all the superheroes ordered by id in ascending order.
-
GET /superheroes?sort=name Returns all the superheroes ordered by name in ascending order.
-
GET /superheroes?sort=age Returns all the superheroes ordered by age in ascending order.
Before going further, let's create the SuperHero class with three attributes id, name, and age. We will be using this class in the further parts of this article.
What is Comparable in Java?
Comparable is an interface in Java that enables comparing an object with other objects of the same type. Comparable interface is provided by the java.lang package. Several built-in classes in Java like Integer, Double, String, etc., implement the Comparable interface.
Comparable is used for sorting objects by natural or default ordering, meaning the object itself knows how it has to be ordered. Example: The SuperHero objects should be ordered by id.
Comparable provides single sorting sequence. It means that the objects can be sorted based on a single data member. Example: The SuperHero object can be sorted based on single attribute like id, name or age.
Syntax
A class has to implement Comparable interface and implement the compareTo() method to enable comparing it with other objects of the same type.
Methods used in Comparable
compareTo()
Comparable interface has exactly one method compareTo() which accepts a single object as parameter and returns an integer value. Java determines the sorting order based on the interger value returned from the compareTo() method.
Syntax
Consider an object x is compared with y via the statement x.compareTo(y), then the value return from the method should be
- 0, if values in x and y are equal.
- Negative, if the value in x is less than in y.
- Positive, if the value in x is greater than in y.
Example of Comparable in Java
We will take our first use case, GET /superheroes. This endpoint should return the list of superheroes ordered by id in ascending order.
We need to make the SuperHero class be sorted by id in ascending order. This can be achieved in two steps.
- Make SuperHero class implement the Comparable interface.
- Override the compareTo() method.
Output
Explanation We have implemented the Comparable interface and overriden the compareTo() method to sort SuperHero objects by id. Collections.sort() internally calls the compareTo() method of SuperHero objects to sort them by id.
What is Comparator in Java?
Comparator is a functional interface in Java that can be used to sort objects, and it is provided by the java.util package.
A functional interface is an interface that contains exactly one abstract method. It is also called Single Abstract Method (SAM) Interfaces.
But wait, this is what the Comparable interface does. Then why do we need the Comparator interface? If a class implements the Comparable interface, then it is aware of how to sort itself because the class itself has implemented the compareTo() method.
This is called default ordering. Comparator is used for custom ordering where the class is unaware of the ordering logic.
Comparator provides multiple sorting sequence (i.e.) sorting objects based on multiple data members. Example: SuperHero objects can be sorted based on multiple attributes like id, name and age.
Syntax
Comparator can be created using a lambda that accepts two objects of the given type and should return an integer value.
Methods used in Comparator
compare()
The compare() method accepts two objects as input parameters and returns an integer value.
Syntax
Comparator decides the sorting order based on the integer value returned from the compare() method.
- 0, if values in o1 and o2 are equal.
- Negative, if the value in o1 is less than in o2.
- Positive, if the value in o1 is greater than in o2.
Example
In this example, we override the compare() method via lambda expression.
The above code is equivalent to
equals()
The equals() method can be used to check if an object and the comparator are equal, meaning; this method can return true only if both the objects are comparators and they impose the exact ordering. The equals() method accepts exactly one object as input and returns a boolean value.
Syntax
The equals() method can be invoked on any comparator instance and, it accepts another comparator instance as input.
Example
In this example, we created two compartors nameComparator and ageComparator and check their equality using the equals() method.
Output
Explanation
In this example, we override the equals() method to check if the comparators are equal by comparing the return value of their compare() method.
- comparator.equals(ageComparator) returns true because they both sort SuperHero objects by age and imposes the same ordering.
- comparator.equals(nameComparator) returns false because comparator and nameComparator sorts SuperHero objects by age and name respectively and doesn't impose the same ordering.
comparing() and thenComparing()
Comparator provides comparing() and thenComparing() methods that are used to apply a series of comparisons to the collection. Multiple comparators can be chained together to apply a series of sorting sequences to a collection of objects.
Syntax
comparing()
The comparing() method accepts a Function as input and returns a Comparator.
- keyExtractor - The function used to extract the Comparable sort key.
thenComparing()
The thenComparing() method accepts a Function and a Comparator as inputs and returns a Comparator.
- keyExtractor - The function used to extract the Comparable sort key.
- keyComparator - The Comparator used to compare the sort key.
Example
Output
Explanation
- The comparator we created is chained with two methods, comparing() and thenComparing() that sorts superHeroes by name ascending and age descending, respectively. Comparator.reverseOrder() specifies that the list should be sorted in descending order.
- After ordering via comparing(SuperHero::getName) the list
Example of Comparator in Java
Consider our second and third use case, GET /superheroes?sort=name and GET /superheroes?sort=age that returns superheroes ordered by name and age in ascending order, respectively. We already overridden the compareTo() method to sort SuperHero objects by id. So, it is not possible to use it to sort by name or age. Here comes the lifesaver Comparator that allows us to create custom comparators. Example: nameComparator, ageComparator.
Output
Explanation We created nameComparator and comparator, which sort SuperHero objects by name and age, respectively. The comparators are created using lambda expressions because Comparator is a functional interface.
A functional interface is an interface that contains exactly one abstract method. It is also called Single Abstract Method (SAM) Interfaces. It can have any number of default methods.
Difference Between Comparable and Comparator in Java
Comparable | Comparator |
---|---|
Comparable is an interface in Java. | Comparator is a functional interface in Java. |
Comparable provides compareTo() method to sort objects. | Comparator provides compare() method to sort objects. |
Comparable is a part of the Java.lang package. | Comparator is a part of the java.util package. |
Comparable can be used for natural or default ordering. | Comparator can be used for custom ordering. |
Comparable provides a single sorting sequence. Ex: Sort either by id or name | Comparator provides multiple sorting sequences. Ex. Sort by both id and name. |
Comparable modifies the class that implements it. | Comparator doesn't modify any class. |
Conclusion
- Comparable is an interface in Java that enables comparing an object with other objects of the same type.
- Comparable is used for the default ordering of the objects.
- Classes implement Comparable interface and overrides the compareTo() method to enable default ordering.
- Comparator is a functional interface in Java that can sort objects. It is used for the custom ordering of objects.
- Comparator provides the compare() method that can be overridden to provide the custom comparison logic.
FAQs
1. Why is Comparator used in Java?
Comparator is used in Java to sort objects based on multiple data members (i.e) based on any conditions because Comparable can be used to sort only based on a single data member. Comparator can also be used when we want a sorting order other than the default sorting order of the class.
2. What is the main purpose of the Comparator interface?
The main purpose of the Comparator interface is to enable sorting based on various criteria apart from the default one.
Consider this Student class. The default order can be by id which can be implemented using Comparable. Comparator enables us to sort his Student object using other criteria like name or age or a combination of both.
3. Is Comparable a functional interface?
No, Comparable is not a function interface. Comparator is a functional interface. If we see the source code of both Comparable and Comparator in Java , we can find that only the Comparator interface is annotated with @FunctionalInterface.
4. How do you make a class comparable?
A class can be made comparable by implementing the Comparable interface and overriding the compareTo() method.