Comparable and Comparator -Part 1



Introduction to Comparable Interface

Suppose you have to arrange a list of numbers in ascending order:

1, 10, 2, 5, 11, 100

You will arrange them as:

1, 2, 5, 10, 11, 100

and suppose you have to arrange a list of names in ascending order :

Sophia, Emilia, Aidan, Jackson, Oliver, Lily

You will arrange them as:

Aidan,  Emilia,  Jackson,  Lily,  Oliver,  Sophia  (Strings are arranged in Lexicographical order)

But now suppose you have a class named Employee as:

public class Employee{ 
 private int empId; 
 private String name; 
 private  String city;
 private int salary; 
 ...
}

and you want to arrange its objects in ascending order. How will you do this?

On what basis you will decide which Employee object should come first and which should come after?

Lets read next section to find answer.

Comparable

Whenever you need to compare instances of a class with each other you should use Comparable interface. In order to compare instances of your Employee class you need to do two things:

1) Implement Comparable interface as:

   public class Employee implements Comparable{
      ...
  }

2) Override compareTo() method of Comparable interface.

Here by implementing Comparable you are saying that now instances of Employee class are comparable and can be compared with each other .

But how will you compare them? Where is the logic to compare them? You will write that logic in compareTo() method.

public int compareTo(T o){
   // your logic to compare instances of Employee
}

Lets explore it in detail.

Comparable interface is present in  java.lang package (So you dont need to import it ! ) and have only one method named compareTo().

While comparing two objects compareTo() method returns a negative integer, zero, or a positive integer on the basis of which it is decided that which object is greater or lesser.

Suppose o1 and o2 are two objects, then if o1.compareTo(o2) :

1) returns a negative integer, it means o1 < o2.
2) returns a positive integer, it means o2< o1
3) returns 0 then o1==o2.

Also note that:

1) If e1 and e2 are not comparable then compareTo() should throw ClassCastException.

2) If e2 is null i.e e1.compareTo(null), then it should throw NullPointerException.


There are two versions of Comarable and compareTo():

1) One is Pre-Java 5 version i.e Non-Generic Form

   Signature:
   
     public interface Comparable and
   
        public int compareTo(Object o)

2) Second from Java 5 onwards, Generic-Form i.e parameterized Comparable.

   Signature:

       public interface Comparable<T> and
   
        public int compareTo(T o)


Lets see their working.

Pre-Java 5 version: Non-generic form

Coming back to our Employee class , suppose you want to arrange employees in acsending order of their ids. Then your code will be:

Employee.java
public class Employee implements Comparable{

 private int empId;
 private String name;
 private  String city;
 private double salary;

@Override
public int compareTo(Object obj){

    /*Checking whether argument is null or not.*/
    if(obj == null){
      throw new NullPointerException("Object passed is null!");
    }

   /*
   If object passed is of type other than Employee, then throw ClassCastException because here we are  comparing instances of only Employee class with each other.
   */
    if(!(obj instanceof Employee)){
         throw new ClassCastException("Not Comparable Objects!");
    }
      
    int id = ((Employee)obj).getEmpId();
      
   /* object represented by 'this' is smaller */
   if(this.getEmpId() < id)  
            return -1;

 /* object represented by 'this' is greater */
   else if(this.getEmpId() > id )
            return 1;

 /* object represented by 'this' and passed object both are equal */
    else
          return 0;
 }

 public void setEmpId(int id){  
        this.empId=id;
 }
 
 public int getEmpId(){  
       return empId;  
 }
  
  public void setName(String name){  
       this.name=name;
 }
 
 public String getName(){  
       return name;  
 }
  
 public void setCity(String city){  
      this.city=city;
 }
 
  public String getCity(){  
       return city;  
  }

 public void setSalary(double sal){  
       this.salary=sal;
  }
 
  public double getSalary(){  
       return salary;  
  }
}

EmployeeComparision.java

public class EmployeeComparision{
 
    public static void main(String args[]){
     
        /* Creating two Employees */
        Employee emp1 = new Employee();      
        emp1.setEmpId(1);
        emp1.setName("Mr. X");
        emp1.setCity("NY");
        emp1.setSalary(25000.0);
      
        Employee emp2 = new Employee();      
        emp2.setEmpId(2);
        emp2.setName("Mr. Y");
        emp2.setCity("New Delhi");
        emp2.setSalary(35000.0);
     
        /*Comparing employees to arrange them in ascending order of their ids.*/
       System.out.println("Employees in acsending order(according to their ids):");

        if(emp1.compareTo(emp2) < 0) {      
            System.out.println("Emp1 < Emp2");
     
        } else if(emp1.compareTo(emp2) > 0) {      
            System.out.println("Emp2 < Emp1");
     
        } else if(emp1.compareTo(emp2) == 0) {      
            System.out.println("Both employees have same Id: emp1==emp2");      
        }
 
    }

}

Output: Emp1 < Emp2

If you change their ids in above code as :

emp1.setEmpId(2);
emp2.setEmpId(1);

Then output will be:

Emp2 < Emp1

Ideally Comparable and compareTo() method should be used to compare instances of same class and to sort them only according to their natural order.

Though we can still write code to compare instances of different classes using Comparable and in the order other than natural order but still one should use it as according to the guidelines set by contract of Comparable.

Natural order

Natural order of elements is something in which those elements can be arranged in their most natural way.

For example, for numerals it would be:

1 2 3 4 5..9 10....  i.e numeric ascending or descending order

For stings it is lexicographical order.

For numerals as strings it would be:

0 1 10 11 2 3 ...    (Note the difference from above given numeric order)

and for user defined classes there is no fixed natural order. It depends on you on what basis you like to see them in sorted manner. For example, a class Book may have attributes like:

public class Book{
  String title;
  String author;
  double price;
  String publisher;
  ...
}

Books can be sorted based on their title or author or price etc. But sorting books according to their title seems more natural. So we can consider it as its natural order. But you can also consider sorting according to author as its natural order. There is no clear cut definition.

Click on Next >> to know about generic form of Comparable.






I would like to know your comments and if you liked the article then please share it on social networking buttons.


No comments:

Post a Comment