Order By clause using Comparators

Here’s a scenario, I have a bean class, let’s say, Employee.

public class Employee {
  private String empID;
  private String name;
  private String department;
  private int salary;

  //Constructor
  public Employee(String empID, String name,
      String department, int salary){
    this.empID = empID;
    this.name = name;
    this.department = department;
    this.salary = salary;
  }

  //getters and setters for the same
}

And I need to sort the objects of Employee, what do I do?
Simple, I could make use of the Comparable or Comparator interface.

Generally, while designing the Employee class if you feel that Employees should be ‘Comparable’, you should provide the most obvious way to compare them.
So in our case the compareTo method would sort the employees in Ascending order of empID.

public class Employee implements Comparable {
  private String empID;
  private String name;
  private String department;
  private int salary;

  //Constructor
  ...
  //getters and setters for the same
  ...

  @Override
  public int compareTo(Employee emp){
    return this.empID.compareTo(emp.getEmpID());
 }
}

If you use a Collection implementation which can be sorted, like ArrayList or a sorted collection itself, like a TreeSet, and then add a bunch of employees in this collection, you can get a sorted version of this collection.

Employee emp1 = new Employee("E001", "Ravi", "IT", 30);
Employee emp2 = new Employee("E002", "Ramesh", "Finance", 50);
Employee emp3 = new Employee("E003", "Deepak", "Finance", 40);
Employee emp4 = new Employee("E004", "Amit", "IT", 60);

List empList = new ArrayList();
//Purposely adding these employees in the list in random order
empList.add(emp2);
empList.add(emp4);
empList.add(emp1);
empList.add(emp3);

//this should sort the list based on the logic in the compareTo method.
Collections.sort(empList);

So when you iterate over this sorted list we would get
E001 Ravi
E002 Ramesh
E003 Deepak
E004 Amit

Now, in future there might be a need to sort employees based on any other property, example: name or salary or department.
How do we do it? Here comes ‘Comparator’ to the rescue.

Comparator decouples the comparing logic from the bean itself.
So you can have various Comparators example NameComparator, SalaryComparator, DepartmentComparator etc.

Below is the implementation for SalaryComparator and the DepartmentComparator and a way to use them.

public class SalaryComparator implements Comparator {
  @Override
  public int compare(Employee e1, Employee e2) {
    return (e1.getSalary() < e2.getSalary() ? -1 : ((e1.getSalary() == e2.getSalary()) ? 0 : 1));
  }
}

public class DepartmentComparator implements Comparator {
  @Override
  public int compare(Employee e1, Employee e2) {
    //we use the String's implementation of compareTo
    return e1.getDepartment().compareTo(e2.getDepartment());
  }
}

//this should sort the list based on the logic in the SalaryComparator's compare method.
Collections.sort(empList, new SalaryComparator());

Ok, now there is a need for you to display the employees in each department in ascending order of their Salaries

Something like

Name Department Salary
Deepak Finance 40
Ramesh Finance 50
Ravi IT 30
Amit IT 60

So in SQL, you would have done this as

select * from Employee order by department, salary;

But in Java to acheive the same using the Comparators we prepared its a bit tricky.
Here’s the solution using the elegant ‘delegate pattern’…

public class DelegateComparator implements Comparator {
  private List comparators;

  //constructor to take a list of specific comparators.
  //This is in line with 'order by department, salary...'
  public DelegateComparator(List comparators){
    if(comparators == null || comparators.isEmpty()){
      throw new IllegalArgumentException();
    }
    this.comparators = comparators;
}

  @Override
  public int compare(Employee e1, Employee e2) {
    if(e1 == e2) {
    return 0; //same object in memory
  }
  int result = 0;
  for(final Comparator comparator : comparators) {
    result = comparator.compare(e1, e2); //delegate to individual comparator
    if(result != 0) {
      //if the objects are not equal in the broader comparison,
      //sorting will be done and we won't do the finer comparisons.
      break;
    }
  }
  return result;
 }
}

You can invoke the above Comparator as shown below

List comparators = new ArrayList();
comparators.add(new DepartmentComparator());
comparators.add(new SalaryComparator());

DelegateComparator delegateComparator = new DelegateComparator(comparators);
Collections.sort(empList, delegateComparator);

Hope this helps.

Advertisements

One response to “Order By clause using Comparators

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s