Comparable and Comparator – a detailed discussion

Introduction

This article is in response to a question asked on one of the groups I am a member of. What is the difference between Comparable and Comparator interfaces in Java. Why there are two interfaces if what they do is provide a method to compare.

This might not seem to be a topic worth discussion for people who are experts in java, but yeah for many of my friends out there, it might help.

Purpose of the article

The article will describe in detail the difference between the interfaces Comparable and Comparator and also define the usages of both of them. One thing we need to understand is that, they can’t be used interchangeably, they are two distinct interfaces and they have their own purpose to exist.

Comparable

You can actually read the comments in the java source code and understand, but I find it tough for a newbie to understand the java doc comments. So here it is in the simplest English possible. When we say Comparable (please note the able in the word), it actually means that the interface enables or gives the classes (which implements it) the ability to compare their instances with each other.

Also, the interface provides a method compareTo which takes a parameter T and returns an integer. This means that if a class implements this interface, it has to provide implementation for the compareTo method as well. Now the logic inside can be anything, anything at all. You are free to write your own comparison logic and say how the object makes a comparison with other objects of the same kind (I say same kind because, its pointless to compare two things of different kind, something like comparing a train and a dog might not make sense).

How to use Comparable?

We define a class, make it implement the Comparable interface and provide implementation code for the compareTo method. Below is a class Car and we want the instances of the Car class to be capable of comparing themselves to each other. There can be more than one property which might be used for a healthy comparison, for simplicity we use just one property for now, the registration number.

The important part in the above code is the compareTo method, it returns 1 if the registrationNumber of this car is greater than the car object passed in the method as parameter. It returns -1 if the situation is reversed and it returns a zero otherwise.

Consequences of using Comparable

As we saw above we, can use Comparable and make the instances of our classes comparable, this satisfies the basic need of comparing two instances of our Car class. Now, here comes the first shock, what if I wrote this car class, generated a jar out of it, and sent it across to all the programmers to use this in their Code?

Everyone includes the jar and instantiate my comparable Car classes and the are happy using it. One of the programmer has a requirement to compare the car objects on the basis of the color code and not the registrationNumber. What is the solution?

Solving the problem – multiple flavors of comparison

He is left with two basic options as mentioned below:
1) Write his/her own Car class, make it implement the Comparable interface and provide implementation code to the compareTo method to compare the color codes instead of registrationNumber.

2) Extend our Car class to something like MySpecialCar extends Car and override the compareTo method to compare the color codes.

If you think you have solved the problem, then sorry to disappoint you, this brings in another case, suppose the same programmer wants to compare the cars based on registration number in one part of his/her code and do the comparison based on color codes in other part of the code.
Is it OK? Now either there has to be one instance of Car and one instance of MySpecialCar to represent just one car so that both the parts of the code can use their comparable instances.

You can image what happens if there are four of five criteria to compare. So, lets try to fix this, and you guessed it right, the answer is Comparator.

How to use Comparator

Now that we know, the problem which arises with usage of Comparable, we can effectively understand the reason Comparator is used. The Comparator is not related to our Car object at all, if we want to Compare our Car objects, we really don’t need the Car object to implement Comparator.

It is something like this, you tell me that you want to compare two Car objects on the basis of registrationNumber and I create a RegistrationNumberComparator class which will extend the Comparator interface and give you an instance of my RegistrationNumberComparator class, which is a comparator ( an object which is specialized in comparing two cars based on their registrationNumber).

Now the second need might arise to compare based on the color codes and I create a ColorCodeComparator class which will extend the Comparator interface and the comparing logic would be to compare the color codes.

The method compare(T a, T b) is the method of the Comparator interface which accepts two parameters, a and b ,where a has to be compared to b. The comparison logic is whatever you write in the implementation.

Code for Comparator

Your Car class need not implement the Comparable interface in the above scenario, hence it will not have any compareTo method as well.

Usage

Mostly we need comparison when there is a need of storing the objects in some ordered fashion in a Collection. Comparisons are also required while sorting and while implementing certain data structures. So you can always pass the desired Comparator to the Collection you are trying to use. It’s up to the user’s choice, how to use the Comparator classes he/she created as a part of the above exercise.

The Debate

The big debate is, if the Comparator interface is so easy and flexible to use, then why use Comparable which has almost no flexibility and the classes cannot be re-used as is, if they implement Comparable.

We can see it very clearly, the restrictions imposed by the Comparable objects help us in restricting the way how objects are compared by default. So, I am sure it is clear to all the readers that Comparable is necessary. To elaborate it, what if I don’t want anyone else to compare the objects I created in any fashion other than I wish. There are several such examples, for e.g.: you would never want an integer to be compared to another by there phonetics(how they sound), you will always want it to be compared by their size.

Yes you guessed it right, all the final classes must implement the Comparable interface, to ensure that they are not mis-compared in any code using them. I always advocate using Comparator until you are trying to make a class final.

Few of them are, String, Integer, Byte etc.

Conclusion

We learnt the difference between Comparable and Comparator, tried to understand the problem when using Comparable and also solved the problem with the Comparator interface.

Hope this helps, happy learning. Please feel free to comment if you like/dislike the article and if you have any question regarding the same.
Download this article as PowerPoint presentation.
Stay connected and stay Subscribed

  • Surya Kant Verma

    Very nice article….

    • dharam

      Thank you for the thought 🙂

  • K M

    Very nice article 🙂 I just dint understand why final classes must implement comparable interface?

  • Renu

    Assume there is a two meeting invite objects. How do you compare them using comparable ,can u give design or logic for the problem

    • dharam

      I believe the Meeting Invite should be composed of the following:
      1) Meeting Object
      2) Recipient Object List

      So, we need to create three classes , Meeting, Recipient, Meeting Invite. depending on your need we can implement comparable to compare the attributes of the Meeting object (organiser, room name, agenda, startTime, endTime, Date etc) encapsulated inside the Meeting Invite and we can also compare the attributes of the mandatory Recipients in the Recepient List in the same compareTo method.

      • Renu

        Thanks for the response.Do I need to implement comparable for class MeetingInvite and write compareTo logic in this class.

        • dharam

          Yes exactly.. Your understanding is perfect.

  • Pingback: Guava Notes: Ordering | sher10ck's blog()