When to use Comparable and Comparator

Viewed 126516

I have a list of objects I need to sort on a field, say Score. Without giving much thought I wrote a new class that implements Comparator, that does the task and it works.

Now looking back at this, I am wondering if I should have instead have the my class implement Comparable instead of creating a new class that implements Comparator. The score is the only field that the objects will be ordered on.

  1. What I have done acceptable as a practice?

  2. Is the right approach "First have the class implement Comparable (for the natural ordering) and if an alternative field comparison is required, then create a new class that implements Comparator" ?

  3. If (2) above is true, then does it mean that one should implement Comparator only after they have the class implement Comparable? (Assuming I own the original class).

19 Answers

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:

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.

Use Comparable:

  • if the object is in your control.
  • if the comparing behaviour is the main comparing behaviour.

Use Comparator :

  • if the object is outside your control and you cannot make them implement Comparable.
  • when you want comparing behaviour different from the default (which is specified by Comparable) behaviour.

If sorting of objects needs to be based on natural order then use Comparable whereas if your sorting needs to be done on attributes of different objects, then use Comparator in Java.

Main differences between Comparable and Comparator:

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

I would say:

  • if the comparison is intuitive, then by all means implement Comparable
  • if it is unclear wether your comparison is intuitive, use a Comparator as it's more explicit and thus more clear for the poor soul who has to maintain the code
  • if there is more than one intuitive comparison possible I'd prefer a Comparator, possibly build by a factory method in the class to be compared.
  • if the comparison is special purpose, use Comparator
  • If at the moment of writing the class you have only one use case of sorting use Comparable.
  • Only when you have more than one strategy of sorting implement a Comparator.

There had been a similar question here: When should a class be Comparable and/or Comparator?

I would say the following: Implement Comparable for something like a natural ordering, e.g. based on an internal ID

Implement a Comparator if you have a more complex comparing algorithm, e.g. multiple fields and so on.

Comparable is the default natural sorting order provided for numerical values are ascending and for strings are alphabetical order. for eg:

Treeset t=new Treeset();
t.add(2);
t.add(1);
System.out.println(t);//[1,2]

Comparator is the custom sorting order implemented in custom myComparator class by overriding a compare method for eg:

Treeset t=new Treeset(new myComparator());
t.add(55);
t.add(56);
class myComparator implements Comparator{
public int compare(Object o1,Object o2){
//Descending Logic
}
}
System.out.println(t);//[56,55]
Related