When to use Comparator and when to use Comparable in Java?

642 views Asked by At

I have an Employee class which has 3 fields like below.

class Employee 
{
  private int empId;
  private String empName;
  private int empAge;

  public Employee(int empId, String empName, int empAge) {
    this.empId = empId;
    this.empName = empName;
    this.empAge = empAge;
}

 // setters and getters

For this I want to sort based on Employee Name(empName), if multiple employees have the same name, then sort based on employee id(empId).

For this I have written a custom comparator using java.util.Comparator like below.

   class SortByName implements Comparator<Employee> 
   {
      public int compare(Employee o1, Employee o2) {
       int result = o1.getName().compareTo(o2.getName());
      if (0 == result) {
        return o1.getEmpId()-o2.getEmpId();
    } else {
        return result;
    }
   }
  }

I have created 8 Employee objects and added to an ArrayList like below.

    List<Employee> empList = new ArrayList<Employee>();

    empList.add(new Employee(3, "Viktor", 28));
    empList.add(new Employee(5, "Viktor", 28));
    empList.add(new Employee(1, "Mike", 19));
    empList.add(new Employee(7, "Mike", 19));
    empList.add(new Employee(4, "Mark", 34));
    empList.add(new Employee(6, "Jay", 34));
    empList.add(new Employee(8, "Gayle", 10));
    empList.add(new Employee(2, "Gayle", 10));          

And sorted the list like below using the above comparator.

Collections.sort(empList,new SortByName());

It has worked absolutely fine. But this can be done using Comparable also like below.

class Employee implements Comparable<Employee> {
private int empId;
private String name;
private int age;

public Employee(int empId, String name, int age) {
    this.empId = empId;
    this.name = name;
    this.age = age;
}

//setters and getters

@Override
public int compareTo(Employee o) {
    int result = this.getName().compareTo(o.getName());
    if (0 == result) {
        return this.getEmpId()-o.getEmpId();
    } else {
        return result;
    }

}

}

Sort the list using Collections.sort(empList);

So I want to know what is the use case or where exactly we use these both? I understood that Comparable is used for natural sorting and can sort using only one field and comparator is used for multiple fields sorting. But if we see my example both the interfaces has the capability to do these both. So please explain me what are the unique features of these both where other one can't be used.

3

There are 3 answers

0
bodyjares On

If you really want to know the unique feature of both.

Implementing Comparable let you compare your Class to an other Class.

Employee implements Comparable<Integer>

A Comparator is an algorithm to compare two instances of a same Class type.

0
Turing85 On

There are classes, which specify an order by their nature (like Strings [lexicographic order is de-facto standard] or Dates). For this classes, you can define their natural order by implementing Comparable<T>. But as I will sketch, a lot of classes can be orderd in more than one way. For this, Comparator<T> is extremely useful.

Ok, so let us look at some other example. Imagine you have a list of Employee as you have mentioned and you want to do some other stuff. For example: you want the flexibility to sort them by name OR by income OR by birth date OR... (imagine you want to choose how to order them). For this case, you may want to specify the exact Comparator to use, depending on the row you selected to sort after.

Another example: The Employee class is already there and does specify some order, but you are unsatisfied with this order. Now you can simply specify your own order with an Comparator and get the behaviour YOU desire.

0
Raman Shrivastava On

Use Comparable if you want to define a default (natural) ordering behavior 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 behavior, this can override the default ordering behavior. You can define any number of ordering behavior, which you can use as required.