Understanding Java Comparable and Comparator: Concepts, Differences, and Code Examples
This article explains Java's two comparison mechanisms—Comparable and Comparator—detailing their purposes, implementation differences, and providing clear code examples that demonstrate how each works and when to use them in sorting custom objects.
Java provides two mechanisms for object comparison and sorting: the Comparable interface and the Comparator interface. Both return an int indicating order, but they differ in design and usage.
Comparable is implemented by a class that defines its natural ordering via the compareTo method. Objects of such a class can be directly sorted by collections utilities like Collections.sort . The method returns a positive integer if the caller is greater than the argument, zero if equal, and a negative integer if less.
public class Domain implements Comparable
{
private String str;
public Domain(String str) {
this.str = str;
}
public int compareTo(Domain domain) {
if (this.str.compareTo(domain.str) > 0)
return 1;
else if (this.str.compareTo(domain.str) == 0)
return 0;
else
return -1;
}
public String getStr() {
return str;
}
}Testing the Comparable implementation:
public static void main(String[] args) {
Domain d1 = new Domain("c");
Domain d2 = new Domain("c");
Domain d3 = new Domain("b");
Domain d4 = new Domain("d");
System.out.println(d1.compareTo(d2)); // 0
System.out.println(d1.compareTo(d3)); // 1
System.out.println(d1.compareTo(d4)); // -1
}The output shows the expected ordering results.
Comparator is a separate object that defines an external ordering strategy via its compare method, which also returns an int with the same semantics. It is useful when a class cannot or should not modify its natural ordering, or when multiple ordering strategies are needed.
public class DomainComparator implements Comparator
{
public int compare(Domain domain1, Domain domain2) {
if (domain1.getStr().compareTo(domain2.getStr()) > 0)
return 1;
else if (domain1.getStr().compareTo(domain2.getStr()) == 0)
return 0;
else
return -1;
}
}Testing the Comparator implementation:
public static void main(String[] args) {
Domain d1 = new Domain("c");
Domain d2 = new Domain("c");
Domain d3 = new Domain("b");
Domain d4 = new Domain("d");
DomainComparator dc = new DomainComparator();
System.out.println(dc.compare(d1, d2)); // 0
System.out.println(dc.compare(d1, d3)); // 1
System.out.println(dc.compare(d1, d4)); // -1
}Because the generic type is fixed, a Comparator implementation can only compare objects of the same type (e.g., two Domain instances).
Summary
For built‑in types like String , Integer , etc., the natural ordering via Comparable is already provided.
For custom classes, use Comparable when a single natural order is sufficient; use Comparator when you need multiple or external ordering strategies.
Comparable resides in java.lang , while Comparator is in java.util , and the former creates tighter coupling with the class.
Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.