Comparable makes a class eligible to be compared with itself by implementing it.
Don't be scared by the definition, we will clear it with below example.
We have seen Collections.sort(..). But in some cases it doesn't work. Let us see below :
Let us see how 'Collections.sort(..)' sorted the Strings in the above case :
1. We have added three Strings to an ArrayList.
2. Passed the ArrayList to 'Collections.sort(..)'
3. Internally 'Collections.sort(..)' opened the ArrayList, found three Strings in it and sorted them accordingly.
Now, consider the Human object. Human object might contain a variable named 'age', also it can contain a variable called 'name'.
So, if we repeat the same steps with Human object.
i.e. We create three 'Human' objects and add it to an ArrayList. Then pass the ArrayList to 'Collections.sort(..)'.
'Collections.sort(..)' opens the ArrayList and is confused because it has three 'Human' objects. And 'Collections.sort(..)' doesn't know either to sort on 'age' or 'name'.
And Comparable comes to rescue.
Let's take the example of Human class.
Let us create four 'Human' objects using constructor and add them to a List.
Since, 'Collections.sort(..)' contains a List of Human objects :
And we need to sort by 'age' and not by name. So, we have to make some tweak in the code telling 'Collections.sort(..)' to sort by 'age'.
And so comes Comparable for rescue. For solving this problem the Human Class needs to implement the Comparable interface and override the compareTo() method.
Tough to understand? Let's make it easy.
We need to follow the below two rules for using 'Comparable' :
1. Implement the 'Comparable' interface.
We have used Generics with Comparable (i.e. Comparable <Human> ), so that the sorting or comparison happens only with the 'Human' class.
2. Override the 'int compareTo(Object o)' in Human class.
* The Comparable interface has an 'int compareTo(Object o)' method, which the Human class needs to override. And the fun is, compareTo(..) can accept 'Human humanCompare' as parameter instead of 'Object o'.
It is only because of Generics we have added with Comparable :
* And the statement :
is sorting the 'Human' objects in the list 'listHuman' in ascending based on 'age'.
Let us relook the process of sorting a List of Human objects by Collection.sort() :
1. We have added three Human objects to an ArrayList.
2. Passed the ArrayList to 'Collections.sort(..)'
3. Internally 'Collections.sort(..)' opened the ArrayList, found three Human objects in it.
4. Since, Human is a class, 'Collections.sort(..)' searches if Human class implements Comparable and overrides 'int compareTo(Object o)'.
5. Now, Collections.sort() expects is a '0', '+ve' or '-ve' returned from compareTo(). Where,
So, in 'return (age - humanCompare.getAge())' the List is sorted in ascending order. And if we would have done the opposite i.e 'return (humanCompare.getAge() - age)' the List would be sorted in descending order.
Now, let us sort the Humans by 'name'.
Similarly, we have to change the compareTo() method of Human class.
But for sorting the Strings we are not substracting the values. Instead we are calling compareTo() again.
Don't panic, think for a while. Can we substract two Strings? No right.
So, we followed the above rule. Look closely, 'name' is a String and we are calling compareTo() on the String.
So, does that mean the String class has a compareTo() method?
Yes, it has. And thats because the String class implements the Comparable interface and overrides the compareTo() method.
Now, does it ring a bell. As in when we were sorting String objects, how it automatically got sorted?
That was because the String class had already implemented the Comparable interface and overriden the compareTo(). Same way we did it for the Human class.
If we want to sort a list which only consist of a variable of a wrapper class (i.e. Integer, String, e.t.c). We do not have to write extra codes to sort them using 'Collections.sort()'. That is because all wrapper classes implement the Comparable interface and overrides the compareTo() method. This ordering is termed as natural ordering.
There were problems with Comparable which was a common problem for everyone.
1. We do not want to put compareTo() method in the Human class. Because Human class is a bean and it is never a good practice to put business logic in a bean.
2. Say at times we want to sort by 'name' and sometimes we want to sort by 'age'. This is not possible using Comparable. With Comparable, you can either sort by 'name' or by 'age'.
Due to the above restrictions, here comes a new interface with better resolution, which is Comparator.