Use Comparable if you want to define a default (natural) ordering behaviour of the object in question, a common practice is to use a technical or natural (database?) identifier of the object for this.
Use Comparator if you want to define an external controllable ordering behaviour, this can override the default ordering behaviour.
See also:
- Sorting an ArrayList of objects using a custom sorting order
Videos
What is the most crucial difference between Comparable and Comparator in Java?
Can a class implement both Comparable and Comparator?
What are Related Courses and Blogs Provided by The Knowledge Academy?
Hi Everyone :) can someone please explain to me what is the difference between Comparator and Comparable ? I mean when should i use one or another? Can i think of it this way : the Comparable's compareTo() defines the standard way of sorting a list (using the 1 arg sort() in Collections) and if i want to compare objects in many different ways i add Comparators to the class and i call the 2 args sort() ? Thanks in advance Melodie
Use Comparable if you want to define a default (natural) ordering behaviour of the object in question, a common practice is to use a technical or natural (database?) identifier of the object for this.
Use Comparator if you want to define an external controllable ordering behaviour, this can override the default ordering behaviour.
See also:
- Sorting an ArrayList of objects using a custom sorting order
I would say that an object should implement Comparable if that is the clear natural way to sort the class, and anyone would need to sort the class would generally want to do it that way.
If, however, the sorting was an unusual use of the class, or the sorting only makes sense for a specific use case, then a Comparator is a better option.
Put another way, given the class name, is it clear how a comparable would sort, or do you have to resort to reading the javadoc? If it is the latter, odds are every future sorting use case would require a comparator, at which point the implementation of comparable may slow down users of the class, not speed them up.
Comparable interface
The Comparable interface defines a type's natural ordering. Suppose you have a list of String or Integer objects; you can pass that list to
Collections.sort(list);
and you will have a sorted list. How? Because String and Integer both implement Comparable interface and the implementations of Comparable interface provide a natural ordering. Its like the class definition saying - "If you find a collection of objects of my type, order them according to the strategy I have defined in the compareTo method".
Now when you define your own type, you can define the natural ordering of the objects of your class by implementing the Comparable interface. See the Java documentation for more information on object ordering.
Comparator interface
The Comparator interface describes how to define custom strategies for object ordering. Suppose we have a simple Person type as below:
public class Person {
String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
Now, by implementing the Comparator interface, you can write different strategies to order the instances of your Person type. For example, consider the two strategies for ordering Person objects given below:
class StrategyOne implements Comparator<Person> {
@Override
public int compare(Person p1, Person p2) {
return p1.getName().length() - p2.getName().length();
}
}
class StrategyTwo implements Comparator<Person> {
@Override
public int compare(Person p1, Person p2) {
return p1.getName().compareTo(p2.getName());
}
}
Here, StrategyOne will order Person objects based on the length of their names, and StrategyTwo will order Person objects based on lexicographic ordering of their names.
The ways to implement Comparator
As you can see, the concrete strategy classes are stateless, hence all instances are functionally equivalent. So, we just need a single instance of any concrete strategy class. Thus, it should be a singleton. Using anonymous classes will create a new instance each time the call is executed. Consider storing the object in a private static final field and reusing it by using static factory methods to access them [Effective Java]. For example, you can reuse the above two concrete strategies as below:
class Strategies {
private static final Comparator<Person> PERSON_NAME_LENGTH_COMPARATOR = new StrategyOne();
private static final Comparator<Person> PERSON_NAME_LEXICAL_COMPARATOR = new StrategyTwo();
public static Comparator<Person> personNameLengthComparator(){
return PERSON_NAME_LENGTH_COMPARATOR;
}
public static Comparator<Person> personNameLexicalComparator(){
return PERSON_NAME_LEXICAL_COMPARATOR;
}
}
Summary
To summarize, the Comparable interface is used to define the natural ordering of a class, and the Comparator interface is used to define particular strategies for object ordering.
In what way is a comparator superior to comparable?
It is not "superior". It is just that the two interfaces are doing (roughly) the same thing in different ways. In the Comparable case the ordering logic is in the object being ordered. In the Comparator case, the logic is in a different class from the objects being declared.
But I don't see a reason why I should use both for sorting employee objects
The only case where it would make sense to use both would be if you needed to be able to sort the objects into different orders. Then you could declare the relevant classes as implementing Comparable for the "natural" order and use Comparator objects to implement the other orders.
By the way, a comparator probably should not implement Comparable, and vice versa.
If a comparator implements Comparable that implies you are trying to order instances of the comparator object itself ...
Your PersonComparator class is misnamed. It should really be called Person.
Could you clarify one thing in your answer that we have already
equals()method from Object class then why theComparatorinterface is facilitating theequals()method again?
A number of points:
You still seem to be confusing the purpose of
ComparableandComparator. Theequalsmethod on aComparatorobject compares the comparator with other comparators!!The
equalsmethod tells you whether two objects are equal ... not which one comes first.The reason that
Comparatoroverridesequalsis solely so that they can clearly document whatequals(Object)does when you call it on aComparatorobject. (The actual behaviour is entirely consistent withObject.equals(Object)... but they obviously thought it necessary to do this because programmers were repeatedly getting the semantics of the method wrong.)
When your class implements Comparable, the compareTo method of the class is defining the "natural" ordering of that object. That method is contractually obligated (though not demanded) to be in line with other methods on that object, such as a 0 should always be returned for objects when the .equals() comparisons return true.
A Comparator is its own definition of how to compare two objects, and can be used to compare objects in a way that might not align with the natural ordering.
For example, Strings are generally compared alphabetically. Thus the "a".compareTo("b") would use alphabetical comparisons. If you wanted to compare Strings on length, you would need to write a custom comparator.
In short, there isn't much difference. They are both ends to similar means. In general implement comparable for natural order, (natural order definition is obviously open to interpretation), and write a comparator for other sorting or comparison needs.
Comparator provides a way for you to provide custom comparison logic for types that you have no control over.
Comparable allows you to specify how objects that you are implementing get compared.
Obviously, if you don't have control over a class (or you want to provide multiple ways to compare objects that you do have control over) then use Comparator.
Otherwise you can use Comparable.