Comparable vs Comparator in Java: Key Differences and When to Use Them

Touseef Khan
4 min readNov 10, 2024

--

In Java, sorting collections is a common task, and two interfaces, Comparable and Comparator, are designed to facilitate custom sorting. While they both serve the purpose of comparison, they differ in approach and usage. Understanding the differences between Comparable and Comparator can help you design cleaner, more flexible code when sorting collections in Java.

Comparable Interface

The Comparable interface is used to define the natural ordering of objects. It is part of java.lang and provides a single method:

int compareTo(T o);

Parameters:

  • T o: This method takes one parameter, o, which represents the object to be compared with the current object (this).
  • Generic Type: T is a placeholder for the type of object, which makes compareTo generic and ensures type safety. For instance, if Book implements Comparable<Book>, the parameter type T becomes Book.

Returns:

  • The compareTo method returns an int, representing the relative ordering of the current object (this) and the specified object (o):
  • Positive integer: If this object is greater than o.
  • Negative integer: If this object is less than o.
  • Zero: If both objects are equal.

When a class implements Comparable, it can be sorted based on a natural order by using the Collections.sort() method without any additional parameters. This natural order is generally an intrinsic sorting sequence, like alphabetical or numerical order.

Example: Using Comparable

Imagine a Book class that has a title and a price. We want to sort books by price in ascending order.

class Book implements Comparable<Book> {
private String title;
private double price;

public Book(String title, double price) {
this.title = title;
this.price = price;
}

public String getTitle() {
return title;
}

public double getPrice() {
return price;
}

@Override
public int compareTo(Book other) {
return Double.compare(this.price, other.price);
}

@Override
public String toString() {
return title + ": $" + price;
}
}

Now, we can sort a list of books by their price:

List<Book> books = Arrays.asList(
new Book("Java Fundamentals", 40.5),
new Book("Data Structures", 35.0),
new Book("Algorithms in Depth", 50.0)
);

Collections.sort(books);
books.forEach(System.out::println);

Output:

Data Structures: $35.0
Java Fundamentals: $40.5
Algorithms in Depth: $50.0

Key Characteristics of Comparable

  • Implements a single sorting sequence (e.g., ascending price).
  • Only one compareTo method can be implemented, limiting it to one natural ordering.
  • Modifying natural order requires altering the class itself, which can lead to reduced flexibility.

Comparator Interface

The Comparator interface, found in java.util, provides more flexibility as it allows you to define multiple sorting sequences. It includes the method:

int compare(T o1, T o2);

Parameters:

  • T o1 and T o2: The compare method accepts two parameters, o1 and o2, which are the objects to be compared.
  • These two parameters allow Comparator to compare any two objects o1 and o2 of the specified type T, making it versatile for defining custom sorting logic outside the model class.

Returns:

  • The compare method returns an int similar to compareTo:
  • Positive integer: If o1 is greater than o2.
  • Negative integer: If o1 is less than o2.
  • Zero: If o1 and o2 are equal.

Using Comparator, we can define multiple custom orders outside the class without altering the class code itself. This is useful when sorting by different attributes.

Example: Using Comparator

Let’s use a Comparator to sort books by title in alphabetical order. We’ll define a separate comparator for sorting by title.

class BookTitleComparator implements Comparator<Book> {
@Override
public int compare(Book book1, Book book2) {
return book1.getTitle().compareTo(book2.getTitle());
}
}

To sort by title:

List<Book> books = Arrays.asList(
new Book("Java Fundamentals", 40.5),
new Book("Data Structures", 35.0),
new Book("Algorithms in Depth", 50.0)
);

Collections.sort(books, new BookTitleComparator());
books.forEach(System.out::println);

Output:

Algorithms in Depth: $50.0
Data Structures: $35.0
Java Fundamentals: $40.5

With Comparator, we can also use lambda expressions or method references to create comparators, making it easy to define custom sorting behavior on the fly.

Example: Using Comparator with Lambdas

Sorting by price in descending order with a lambda expression:

Collections.sort(books, (book1, book2) -> Double.compare(book2.getPrice(), book1.getPrice()));

Key Characteristics of Comparator

  • Allows multiple sorting sequences (e.g., by title, by price).
  • Comparator instances can be passed into sorting methods like Collections.sort().
  • Comparators are separate from the model class, promoting code reusability and flexibility.
  • Lambdas and method references simplify creating comparators on the fly.

Comparable vs Comparator: When to Use Which?

When to Use Comparable:

  • Use Comparable when there is a single, default sorting order that makes sense for the class (e.g., sorting employees by ID or names alphabetically).
  • Good for models where the “natural order” is unlikely to change.

When to Use Comparator:

  • Use Comparator when you need multiple sorting sequences for the same object (e.g., sorting products by price, name, or rating).
  • Ideal when you don’t want to modify the model class to introduce sorting logic.
  • Use Comparator with lambdas for a concise, inline sorting definition.

Conclusion

Both Comparable and Comparator play essential roles in Java's sorting mechanism. Comparable is great for defining a natural, intrinsic order in a class, while Comparator provides flexibility for external, customizable sorting criteria. Depending on the requirements of your project, using the right interface will allow you to achieve efficient, readable, and reusable code for sorting objects in Java.

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Touseef Khan
Touseef Khan

Written by Touseef Khan

Experienced full-stack developer proficient in Java, AEM, & .NET. Let's connect: https://www.linkedin.com/in/touseef-khan-19214930/

No responses yet

Write a response