Java Comparators — When comparison doesn’t go natural

Sumit Kumar
4 min readSep 7, 2020

--

Have you ever tried to compare two objects based on their size? or Create a todo list application to prioritize your work based on its type?

Comparing two objects based on their size

Java inherits two popular methods equals(Object o) and hashCode() from its Object class for comparing two objects based on their values inside and their address locations (via hashcodes).

Operators like < (less than) and > (greater than) do not go well with objects in Java. The Object class does not provide any methods for “less than” or “greater than” comparison. For this type of comparison, java follows the natural ordering of these objects.

Now, the question comes, what is natural ordering? Well technically, the natural ordering defines some rules that govern the relative placement of elements/values/objects based on their type. For example, String values will be sorted in lexicographical order, Date values will be sorted in chronological order, Integer values will be sorted in ascending/descending (Signed numeric) order, and so on.

Java provides a standard way for comparing its objects based on their natural ordering by implementing compareTo(Object o) method of the Comparable interface. Here’s the syntax for using a Comparable interface in java.

public interface Comparable<T> {

public int compareTo(T other);

}

A call to A.compareTo(B ) should return:

  • a value < 0, if A comes “before” B in the ordering,
  • a value > 0, if A comes “after” B in the ordering,
  • or exactly 0 if A and B are considered “equal” in the ordering

Let’s suppose we wish to develop a movie database application (just like IMDb) to rate movies based on certain parameters. Consider a Movie object that has members like rating, name, year of release, critics score etc. Suppose, we wish to sort a list of Movies based on their year of release. Since, year is a signed numeric value (Integer), it’ll be ordered naturally.

We can implement the Comparable interface with the Movie class, and we can override the compareTo() method as follows:

// sort movies by year of release

public int compareTo(Movie m)

{

return this.year — m.year;

}

so far so good…

Now, let's say, the client wants us to order movies in our Movie database application based on critics' score and user’s rating.

This is true for most real-life scenarios, as we want to compare objects based on different parameters. This is the situation where we use Java Comparator interface since Comparable.compareTo(Object o) works only on default comparison (i.e., natural ordering) and we cannot customize it as per our requirements.

Comparing objects based on different attributes

Comparators, unlike Comparable, is external to the element type we are comparing.

  • It allows us to define multiple orderings for the same type of object
  • It allows us to define a specific ordering for an object type even if there’s no obvious “natural ordering” for that type

We can create multiple separate classes (that implements Comparator interface) to compare objects as per requirements. Here’s the syntax for using Comparator interface in java:

public interface Comparator<T>{

public int compare(T first, T second);

}

Now, to compare movies based on their critic's score and user’s rating, we can do the following:

  • Create different classes that implements Comparator (and thus compare()) to customize our comparison

// using compare(Object o1, Object o2) to compare movies based on ciritic’s score

public int compare(Movie m1, Movie m2)

{

if (m1.getCriticScore() < m2.getCriticScore()) return -1;

if (m1.getCriticScore() > m2.getCriticScore()) return 1;

else return 0;

}

// using compare(Object o1, Object o2) to compare movies based on user’s rating

public int compare(Movie m1, Movie m2)

{

if (m1.getUserRating() < m2.getUserRating()) return -1;

if (m1.getUserRating() > m2.getUserRating()) return 1;

else return 0;

}

To summarize, use Comparable when you want to compare objects based on their natural ordering (the Object inherently knows how to compare itself) and use Comparator when you want to customize your comparison based on different parameters/attributes of your object.

You can refer to the official documentation of Comparator interface defined in Java Standard API by following the given link.

--

--

Sumit Kumar
Sumit Kumar

Written by Sumit Kumar

Assistant Professor of Computer Science at The NorthCap University, Gurugram, India.

No responses yet