Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to use Comparable and Comparator

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.


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.

Comparable - java.lang.Comparable: int compareTo(Object o1)

A comparable object is capable of comparing itself with another object. The class itself must implements the java.lang.Comparable interface in order to be able to compare its instances.

  • Capable of comparing current object with the provided object.
  • By using this we can implement only one sort sequence based on the instances properties. EX: Person.id
  • Some of the Predefined Classes like String, Wrapper classes, Date, Calendar has implemented Comparable interface.

Comparator - java.util.Comparator: int compare(Object o1, Object o2)

A comparator object is capable of comparing two different objects. The class is not comparing its instances, but some other class’s instances. This comparator class must implement the java.util.Comparator interface.

  • Capable of comparing any two Objects of Same Type.
  • By using this we can implement many sort sequence and name each, based on the instances properties. EX: Person.id, Person.name, Person.age
  • We can implement Comparator interface to our Pre-defined classes for Customized sorting.

Example:

public class Employee implements Comparable<Employee> {

    private int id;
    private String name;
    private int age;
    private long salary;

    // Many sort sequences can be created with different names.
    public static Comparator<Employee> NameComparator = new Comparator<Employee>() {         
        @Override
        public int compare(Employee e1, Employee e2) {
            return e1.getName().compareTo(e2.getName());
        }
    };
    public static Comparator<Employee> idComparator = new Comparator<Employee>() {       
        @Override
        public int compare(Employee e1, Employee e2) {
            return Integer.valueOf(e1.getId()).compareTo(Integer.valueOf(e2.getId()));
        }
    };

    public Employee() { }
    public Employee(int id, String name, int age, long salary){
        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
    }
    // setters and getters.

    // Only one sort sequence can be created with in the class.
    @Override
    public int compareTo(Employee e) {
    //return Integer.valueOf(this.id).compareTo(Integer.valueOf(e.id));
    //return Character.toString(this.name.charAt(0)).compareToIgnoreCase(Character.toString(e.name.charAt(0)));
        if (this.id > e.id) {
            return 1;
        }else if(this.id < e.id){
            return -1;
        }else {
            return Character.toString(this.name.charAt(0)).compareToIgnoreCase(Character.toString(e.name.charAt(0)));
        }

    }   

    public static void main(String[] args) {

        Employee e1 = new Employee(5, "Yash", 22, 1000);
        Employee e2 = new Employee(8, "Tharun", 24, 25000);

        List<Employee> list = new ArrayList<Employee>();
        list.add(e1);
        list.add(e2);
        Collections.sort(list); // call @compareTo(o1)
        Collections.sort(list, Employee.nameComparator); // call @compare (o1,o2)
        Collections.sort(list, Employee.idComparator); // call @compare (o1,o2)
    }
}
  • For customized sorting we go for comparator @compare(o1, o2) for other scenarios we go for comparable @compareTo(o1), with out changing code if we want to sort more than one field then we use comparator.

For Java 8 Lambda : Comparator refer to my post.