1) Comparator in Java is defined in java.util package while Comparable interface in Java is defined in java.lang package, which very much says that Comparator should be used as an utility to sort objects which Comparable should be provided by default.
2) Comparator interface in Java has method public int compare (Object o1, Object o2) which returns a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second. While Comparable interface has method public int compareTo(Object o) which returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.
3) If you see then logical difference between these two is Comparator in Java compare two objects provided to him, while Comparable interface compares "this" reference with the object specified. I have shared lot of tips on how to override compareTo() method and avoid some common mistakes programmer makes while implementing Comparable interface.
4) Comparable in Java is used to implement natural ordering of object. In Java API String, Date and wrapper classes implements Comparable interface.Its always good practice to override compareTo() for value objects.
5) If any class implement Comparable interface in Java then collection of that object either List or Array can be sorted automatically by using Collections.sort() or Arrays.sort() method and object will be sorted based on there natural order defined by CompareTo method.
6)Objects which implement Comparable in Java can be used as keys in a SortedMap like TreeMap or elements in a SortedSet for example TreeSet, without specifying any Comparator.
These were combination of some theoretical and practical differences between Comparator and Comparator interface in Java. It does help you to decide when to use Comparator vs Comparable but things will be more clear when we some best practices around using both of these interfaces. Now let’s see an example of Comparator in Java:
Example of using Comparator and Comparable in Java
So in Summary if you want to sort objects based on natural order then use Comparable in Java and if you want to sort on some other attribute of object then use Comparator in Java. Now to understand these concepts lets see an example or real life coding:
1) There is class called Person, sort the Person based on person_id, which is primary key in database
2) Sort the Person based on there name.
For a Person class, sorting based on person_id can be treated as natural order sorting and sorting based on name field can be implemented using Comparator interface. To sort based on person_id we need to implement compareTo() method.
public class Person implements Comparable {
private int person_id;
private String name;
/**
* Compare current person with specified person
* return zero if person_id for both person is same
* return negative if current person_id is less than specified one
* return positive if specified person_id is greater than specified one
*/
@Override
public int compareTo(Object o) {
Person p = (Person) o;
return this.person_id - o.person_id ;
}
….
}
private int person_id;
private String name;
/**
* Compare current person with specified person
* return zero if person_id for both person is same
* return negative if current person_id is less than specified one
* return positive if specified person_id is greater than specified one
*/
@Override
public int compareTo(Object o) {
Person p = (Person) o;
return this.person_id - o.person_id ;
}
….
}
Generally you should not use difference of integers to decide output of compareTo method as result of integer subtraction can overflow but if you are sure that both operands are positive then its one of the quickest way to compare two objects. See my post things to remember while overriding compareTo in Java for more tips on compareTo.
And for sorting based on person name we can implement compare(Object o1, Object o2) method of Java Comparator class.
/**
* Comparator implementation which sorts Person objects on person_id field
*/
public class SortByPerson_ID implements Comparator{
public int compare(Object o1, Object o2) {
Person p1 = (Person) o;
Person p2 = (Person) o;
return p1.getPersonId() - p2.getPersonId();
}
}
* Comparator implementation which sorts Person objects on person_id field
*/
public class SortByPerson_ID implements Comparator{
public int compare(Object o1, Object o2) {
Person p1 = (Person) o;
Person p2 = (Person) o;
return p1.getPersonId() - p2.getPersonId();
}
}
Similar guidelines applies while implementing compare() method as well and instead of using subtraction operator, its better to use logical operator to compare whether two integers are equal to, less than or greater than. You can write several types of Java Comparator based upon your need for example reverseComparator , ANDComparator , ORComparator etc which will return negative or positive number based upon logical results. String in Java even provides an special comparator called CASE_INSENSITIVE_ORDER, to perform case insensitive comparison of String objects.
How to Compare String in Java
String is immutable in Java and one of the most used value class. For comparing String in Java we should not be worrying because String implements Comparable interface and provides a lexicographic implementation for CompareTo method which compare two strings based on contents of characters or you can say in lexical order. You just need to call String.compareTo(AnotherString) and Java will determine whether specified String is greater than , equal to or less than current object. See my post 4 example to compare String in Java for alternatives ways of comparing String.
How to Compare Dates in Java
Dates are represented by java.util.Date class in Java and like String, Date also implements Comparable in Java so they will be automatically sorted based on there natural ordering if they got stored in any sorted collection like TreeSet or TreeMap. If you explicitly wants to compare two dates in Java you can call Date.compareTo(AnotherDate) method in Java and it will tell whether specified date is greater than , equal to or less than current String. See my post 3 ways to compare Dates in Java for more alternatives of comparing two dates.
When to use Comparator and Comparable in Java
At last let’s see some best practices and recommendation on when to use Comparator or Comparable in Java:
1) If there is a natural or default way of sorting Object already exist during development of Class than use Comparable. This is intuitive and you given the class name people should be able to guess it correctly like Strings are sorted chronically, Employee can be sorted by there Id etc. On the other hand if an Object can be sorted on multiple ways and client is specifying on which parameter sorting should take place than useComparator interface. for example Employee can again be sorted on name, salary or department and clients needs an API to do that. Comparator implementation can sort out this problem.
2) Some time you write code to sort object of a class for which you are not the original author, or you don't have access to code. In these cases you can not implement Comparable and Comparator is only way to sort those objects.
3) Beware with the fact that How those object will behave if stored in SorteSet or SortedMap like TreeSet and TreeMap. If an object doesn't implement Comparable than while putting them into SortedMap, always provided corresponding Comparator which can provide sorting logic.
4) Order of comparison is very important while implementing Comparable or Comparator interface. for example if you are sorting object based upon name than you can compare first name or last name on any order, so decide it judiciously. I have shared more detailed tips on compareTo on my post how to implement CompareTo in Java.
5) Comparator has a distinct advantage of being self descriptive for example if you are writing Comparator to compare two Employees based upon there salary than name that comparator as SalaryComparator, on the other hand compareTo()