Thursday, June 30, 2011

Comparable and Comparator interfaces-Part 1

I have tried to make the article to be detailed and at the same time to the point.
 Comparable: It is an interface.If your class implements it object of your class can be compared with other objects of the same class. To compare you must implement the compareTo method in your class. compareTo must be consistent with the equals method (but not mandatory). For further details please refer to Comparable documentation.
    compareTo(Object o): Can be called like e1.compareTo(e2). Implementor should ensure following things:
  1. It should return Negative integer (if e1 < e2), 0 (if e1 = e2), Positive integer (if e1 > e2)
  2. It should throw ClassCastException if object types of e1 and e2 are not comparable
  3. It should throw NullPointerException if e2 passed is null
 Comparator: It is again an interface only. It is also used to provide ordering but you need not modify the class to provide the ordering to it. It has a compare(Object e1, Object e2). You create a separate class which implements the Comparator interface and implement the compare method
which does the actual work.
    compare(Object e1, Object e2): Can be called like compare(e1, e2)
  1. It should return Negative integer (if e1 < e2), 0 (if e1 = e2), Positive integer (if e1 > e2)
  2. It should throw ClassCastException if object types of e1 and e2 are not comparable
  3. It should throw NullPointerException if either e1 or e2 or both passed are null

Following are some classes in Java which implement comparable interface:
Note:
ClassNatural Ordering that the class has
Byte, Short, Integer, Long, Float, Double, BigInteger, BigDecimalSigned numerical
CharacterUnsigned numerical
BooleanBoolean.True > Boolean.False
StringLexographic
DateChronological
FileSystem-dependent lexicographic path name
CollationKeyLocale-specific lexicographic
Other classes implementing Comparable interface are URI, Charset, ByteBuffer, ShortBuffer, CharBuffer, IntBuffer, FloatBuffer, DoubleBuffer, LongBuffer

Example: Comparable
We has an Employee class which we need to store in a list in the ascending order of their name to display on the screen. Here goes the code for Employee class and Test class to check the ordering.

package blog.javaespresso.comparable.example.bean;

import java.util.Date;
public class Employee implements Comparable<employee>{
 public Employee(){}
 public Employee(int empId,String name,double salary,Date dateOfJoining){
  this.empId = empId;this.name =  name;
  this.salary =  salary;this.dateOfJoining = dateOfJoining;
 }
 private int empId;
 private String name;
 private double salary;
 private Date dateOfJoining;
 @Override
 public int compareTo(Employee o) {
  if(o == null){
   throw new NullPointerException("compareTo: Argument passed is null");
  }
  if(this.getClass().equals(o.getClass())){
   Employee e = (Employee) o;
   return this.getName().compareTo(e.getName());
  }else{
   throw new ClassCastException("compareTo: Objects are not comparable");
  }
 }
 // setters and getters
 public int getEmpId() {return empId;}
 public void setEmpId(int empId) {this.empId = empId;}
 public String getName() {return name;}
 public void setName(String name) {this.name = name;}
 public double getSalary() {return salary;}
 public void setSalary(double salary) {this.salary = salary;}
 public Date getDateOfJoining() {return dateOfJoining;}
 public void setDateOfJoining(Date dateOfJoining) {this.dateOfJoining = dateOfJoining;
}
}

Now let us see the test class:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import blog.javaespresso.comparable.example.bean.Employee;

public class TestEmployeeSorting {
 public static void main(String[] args) {
  Employee e1 = new Employee(1,"A",20000.00,new Date(2010,12,11));
  Employee e2 = new Employee(2,"A",22000.00,new Date(2009,12,11));
  Employee e3 = new Employee(3,"A",10000.00,new Date(1990,12,11));
  Employee e4 = new Employee(4,"F",19000.00,new Date(2001,12,11));
  Employee e5 = new Employee(5,"E",24000.00,new Date(2006,12,11));
  List<Employee> list = new ArrayList<Employee>();
  list.add(e1);list.add(e2);list.add(e3);list.add(e4);list.add(e5);
  // PRINT BEFORE SORTING
  System.out.println("BEFORE SORTING");
  System.out.println("===============================================================");
  System.out.println("ID  Name  Salary  Date Of Joining");
  System.out.println("===============================================================");
  for (Employee employee : list) {
   System.out.println(employee.getEmpId()+"\t\t "+employee.getName()
     +"\t\t"+employee.getSalary()+"\t\t "+
     employee.getDateOfJoining().getDay()+"-"+employee.getDateOfJoining().getMonth()
     +"-"+employee.getDateOfJoining().getYear());
  }

  // sorting the Employee object
  Collections.sort(list);
  // PRINT AFTER SORTING
  System.out.println("\n\nAFTER SORTING");
  System.out.println("===============================================================");
  System.out.println("ID  Name  Salary  Date Of Joining");
  System.out.println("===============================================================");
  for (Employee employee : list) {
   System.out.println(employee.getEmpId()+"\t\t "+employee.getName()
     +"\t\t"+employee.getSalary()+"\t\t "+
     employee.getDateOfJoining().getDay()+"-"+employee.getDateOfJoining().getMonth()
     +"-"+employee.getDateOfJoining().getYear());
  }
 }
}

To sort in the descending order of name, you just need to call reverse(List list) method of Collections class after doing sorting. For example,

Collections.sort(list);
Collections.reverse(list);
  // PRINT AFTER SORTING
  System.out.println("\n\nAFTER SORTING");

Related Articles
Comparable and Comparator interfaces-Part 2
Sorting objects with more than one attribute

14 comments:

  1. Nice job. Direct and to the point. Thanks!

    ReplyDelete
  2. A doubt. Can we not implement Comparator interface for Employee class?

    ReplyDelete
  3. one more doubt, can we not implement what we have achieved with Comparator interface using Comparable interface?

    ReplyDelete
  4. Deciding whether Comparator's compare method should throw a NullPointerException isn't as clear. See http://stackoverflow.com/questions/2858628/comparable-and-comparator-contract-with-regards-to-null/2858691#2858691.

    ReplyDelete
  5. both are doing the same thing by using different implementation..what is the difference??

    ReplyDelete
  6. Difference is between the way both are used as explained inn the article.. But in major cases Comparator becomes a better choice as it decouples the sorting logic from the entity being sorted...

    ReplyDelete
  7. Not to knit-pick, but there is a typo in the code that may confuse some people. The code as it stands now will not compile. Specifically, the type parameter to the generic Comparable should be Employee and not employee. Therefore the following line:

    public class Employee implements Comparable{

    should actually be:

    public class Employee implements Comparable{

    ReplyDelete
    Replies
    1. Hi,

      I saw the declaration but it is same only where is the difference in your two lines

      Delete
  8. when is the compareto method is called.? is it called internally?

    ReplyDelete
  9. This comment has been removed by the author.

    ReplyDelete