Comparator interface vs Comparable interface
Comparator interface vs Comparable interface
Streams-api has many nice features that support sort by using Comparators on the fly.
In Java language, the Comparator interface makes use of default methods heavily. See https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html
Let’s break down Comparable and Comparator. Both are Java interfaces used to define how objects of a particular class are ordered (sorted). The key difference lies in where the comparison logic resides and how flexible it is.
Comparable<T>
- Purpose: Defines the natural ordering for objects of a class. This is the single, most obvious way objects of this class should be sorted by default.
- Interface:
java.lang.Comparable<T> - Method: Requires implementing a single method:
public int compareTo(T other) - Implementation: The class whose instances need to be sorted must implement this interface itself.
- Logic: The
compareTomethod comparesthisobject with theotherobject passed as an argument.- Returns a negative integer if
thisobject comes beforeother. - Returns zero if
thisobject is equal tootherin terms of ordering. - Returns a positive integer if
thisobject comes afterother.
- Returns a negative integer if
- Use Case: Used by sorting methods like
Collections.sort(list)andArrays.sort(array)when no explicitComparatoris provided. Also used by sorted data structures likeTreeSetandTreeMapby default. - Flexibility: Limited. Only allows one sorting implementation directly within the class.
- Example Classes:
String,Integer,Double,Dateall implementComparablefor their natural alphabetical/numerical/chronological order.
Comparator<T>
- Purpose: Defines custom or multiple alternative orderings for objects of a class. It decouples the comparison logic from the class being compared.
- Interface:
java.util.Comparator<T> - Method: Requires implementing a single method:
public int compare(T o1, T o2)(Note: takes two objects). - Implementation: A separate class implements this interface. This separate class defines how to compare two objects of type
T. Often implemented using separate classes, anonymous inner classes, or lambda expressions (Java 8+). - Logic: The
comparemethod compares the two objectso1ando2.- Returns a negative integer if
o1comes beforeo2. - Returns zero if
o1is equal too2in terms of this specific ordering. - Returns a positive integer if
o1comes aftero2.
- Returns a negative integer if
- Use Case: Used when:
- You need to sort objects based on different criteria (e.g., sort
Personobjects by name, then by age, then by ID). - You want to sort objects of a class you cannot modify (e.g., from a third-party library).
- You want to provide a specific order to methods like
Collections.sort(list, comparator)orArrays.sort(array, comparator). - You want to create sorted data structures like
TreeSetorTreeMapwith a custom order (new TreeSet<>(myComparator)).
- You need to sort objects based on different criteria (e.g., sort
- Flexibility: High. Allows multiple, independent sorting strategies for a single class without modifying the class itself.
Analogy
Comparable: Think of people having an inherent, natural way to compare themselves, like by height. Theheightcomparison logic is part of thePersonclass itself (compareTo).Comparator: Think of bringing in external judges. One judge compares people by weight (WeightComparator), another by running speed (SpeedComparator). These judges (Comparatorimplementations) are separate from thePersonclass and provide different ways to order people.
Comparison Table
| Feature | Comparable<T> |
Comparator<T> |
|---|---|---|
| Purpose | Natural, default ordering | Custom, multiple, external orderings |
| Interface | java.lang.Comparable<T> |
java.util.Comparator<T> |
| Key Method | int compareTo(T other) |
int compare(T o1, T o2) |
| Implementation | Implemented by the class itself | Implemented by a separate class |
| # Sort Logics | One per class | Many per class |
| Modification | Requires modifying the class | Does not require modifying the class |
| Default Sorting | Used by default (sort(list)) |
Used when explicitly passed (sort(list, c)) |
| Package | java.lang |
java.util |
When to Use Which
- Use
Comparablewhen there’s a clear, single, natural way to order objects of your class. Implement it directly in your class. - Use
Comparatorwhen:- You need multiple ways to sort objects.
- You need to sort objects of a class you cannot modify.
- You want to keep sorting logic separate from the domain object’s core responsibilities.
The Comparator interface is more flexible and provides more control over the sorting behavior of objects. If you need to sort objects based on different criteria or if the objects do not implement the Comparable interface, you should use the Comparator interface. On the other hand, if you want to define the natural ordering of an object, you should use the Comparable interface.