Java Comparable VS Comparator

Introduction

In our previous two tutorials Java Comparable & Java Comparator, we examined the details of java.lang.Comparable and java.util.Comparator. After reading and understanding both, one question still remained, Which one should be used because both seem to do the same thing? The only difference is the signatures of their respective methods. So, in this post we try to figure out the answer to this deceptively simple question, Comparable vs Comparator.

Comparison

Let’s compare the two interfaces side by side and see if one is better than the other and which to use when.

java.lang.Comparablejava.util.Comparator
int objOne.compareTo(objTwo)int compare(objOne, objTwo)
Returns
negative if objOne < objTwo
zero if objOne == objTwo
positive if objOne > objTwo
Same as Comparable
You must modify the class whose
instances you want to sort.
You build a class separate from the class whose instances you
want to sort.
Only one sort sequence can be created.Many sort sequences can be created.
Implemented frequently in the API by: String, Wrapper classes, Date, Calendar.Meant to be implemented to sort instances of third-party
classes.

 

int objOne.compareTo(objTwo) vs int compare(objOne, objTwo)

It just seems like a method signature difference, but there is a subtle difference.

A comparable object is capable of comparing itself with another object. The class itself must implement the java.lang.Comparable interface in order to be able to compare its instances. Whereas, A comparator object is capable of comparing two different objects. The class is not comparing its instances, but some other class’s instances. This comparator class must implement the java.util.Comparator interface.

The second comparison is not a difference, it basically specifies the return values of the methods and they are same for both.

 

You must “modify” the class whose instances you want to sort vs You build a class separate from the class whose instances you want to sort.

This is a very important difference. Read it again!!

To understand this better let’s take the example of our Student class. In case of comparable, your Student class implements Comparable interface and overrides compareTo method. Let’s say at one point, your teammate needs to sort students based on their rollNumbers.  So his student class would look something like:

But if at some later point of time you need your students to be sortable based on their marks, the above Class won’t work. You will have to modify the compareTo implementation for marksObtained by the student. Something like:

 

So, the problem here is you need to modify your class every time the sorting requirement changes which is not a good idea. As the Open/Close design principle goes “software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification

If you violate this principle you might end up writing the test cases for the class which was already tested and worse, you might end up breaking someone else’s code who depended on Student’s rollNumber for sorting (your team mate). Right?

So, now the Comparator comes into picture, if instead of using Comparable you had used Comparator, you wouldn’t have to violate any design principle. Your would write his Comparators like:

And you can write:

Now, you don’t need to change the existing code and break someone else’s code. Any Student aor subtype can now use these comparators to do the comparisons.

 

Only one sort sequence can be created vs Many sort sequences can be created.

As we saw above every time the requirement changed, we needed to modify our Comparable Student because with Comparable we have only one sort sequence but with Comparator we created two different sort sequences. You can create even a third one which will let you sort based on Student names.

 

Implemented frequently in the API by: String, Wrapper classes, Date, Calendar vs Meant to be implemented to sort instances of third-party classes.

The final comparison is just about the application of the two interfaces. Where they are used at present and what are the areas of their usage.

Verdict

So, after examining all the difference carefully, have you been able to decide which interface is better. Which should be given preference?

It seems Comparator is the way to go always but this is not quite right because it is not about using one or the other. You should think about leveraging both as it will make your code more flexible and more robust at the same time.

So, if sorting of objects needs to be based on a natural order then use Comparable whereas if sorting needs to be done on different attributes of the object, use Comparator in Java.

For example, telephone directories are always sorted by the Last Name of the contacts. Which is quite natural and easier for the users, so, Comparable seems like a good choice here. But what if, some one wants to sort contacts by the city, the contacts live in, so that they could post, let’s say, a common message to all the residents of that city. Now, in this situation sorting contacts by city name seems quite reasonable but this doesn’t mean that you go ahead and start changing your existing class. Instead, you can write a CityComparator, a brand new sorting sequence which will not break the existing code and can be reused in future if similar requirement arises.

Let’s see how to use Comparable & Comparator together using the AddressBook example.

Comparable & Comparator together

To begin with, we need a Contact class whose instances will be in the Address Book.
We will be using just two fields, name and city to keep the examples simple. Natural order of sorting for a Contact is by name.

Contact.java

Next, we need an address-book, which will be read by the user using different sort orders.

AddressBook.java

So far the users of address-book can view the contacts sorted by their names because as we mentioned earlier, contacts have a natural order by-name.

Now comes the second part of our example. What if, user wants to see the contacts sorted by their city instead of their name. Let’s write a comparator which allows us to do just that.

CityComparator.java

Now, let’s test run our code:

AddressBookDemo.java

 

I hope, now we are clear on how to use Comparable and Comparator and how to answer the important interview question on Comparable vs Comparator like

  • Which to choose when?
  • Which is better or preferred over the other?

Related Posts

If you have any query or feedback, please let me know. Take care!!