Thursday, June 30, 2011

Comparable and Comparator interfaces-Part 2

We have already seen the Comparable interface at work now let us see how to create comparators.

We will use the same Employee class.But without any Comparable interface implmentation. Now we have EmployeePojo class listed below:

package blog.javaespresso.comparable.example.bean;

import java.util.Date;

public class EmployeePojo {
 public EmployeePojo(){}
 public EmployeePojo(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;

 // 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;}
}

So objective is we need to display a report and report has options of sorting the employees either by name or date of joining.
take a look at the code listings:
Employee Name Comparator Class
package package blog.javaespresso.comparator.example.customcomparator;

import java.util.Comparator;
import blog.javaespresso.comparable.example.bean.EmployeePojo;

public class EmployeeNameComparator implements Comparator<EmployeePojo>{

 @Override
 public int compare(EmployeePojo e1, EmployeePojo e2) {
  if(e1 == null || e2 == null){
   throw new NullPointerException("compareTo: Argument passed is null");
  }
   return e1.getName().compareTo(e2.getName());
 }

}
Employee Date Of Joining Comparator Class
package package blog.javaespresso.comparator.example.customcomparator;

import java.util.Comparator;
import blog.javaespresso.comparable.example.bean.EmployeePojo;

public class EmployeeDOJComparator implements Comparator<EmployeePojo>{

 @Override
 public int compare(EmployeePojo e1, EmployeePojo e2) {
  if(e1 == null || e2 == null){
   throw new NullPointerException("compareTo: Argument passed is null");
  }
   return new Integer(e1.getDateOfJoining().compareTo(e2.getDateOfJoining()));
 }

}
Employee Comparator sorting test class:
We first create some employee objects and then first we sort them using name comparator and then using DOJ comparator
package blog.javaespresso.comparator.example.test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import blog.javaespresso.comparable.example.bean.EmployeePojo;
import blog.javaespresso.comparator.example.customcomparator.EmployeeDOJComparator;
import blog.javaespresso.comparator.example.customcomparator.EmployeeNameComparator;

public class TestEmployeeComparatorSorting {
 public static void main(String[] args) {
  EmployeePojo e1 = new EmployeePojo(1,"A",20000.00,new Date(2010,12,11));
  EmployeePojo e2 = new EmployeePojo(2,"A",22000.00,new Date(2009,12,11));
  EmployeePojo e3 = new EmployeePojo(3,"A",10000.00,new Date(1990,12,11));
  EmployeePojo e4 = new EmployeePojo(4,"F",19000.00,new Date(2001,12,11));
  EmployeePojo e5 = new EmployeePojo(5,"E",24000.00,new Date(2006,12,11));
  List<EmployeePojo> list = new ArrayList<EmployeePojo>();
  list.add(e1);list.add(e2);list.add(e3);list.add(e4);list.add(e5);

  Collections.sort(list,new EmployeeNameComparator());
  // PRINT AFTER SORTED BY NAME
  System.out.println("AFTER SORTED BY NAME");
  System.out.println("===============================================================");
  System.out.println("ID  Name  Salary  Date Of Joining");
  System.out.println("===============================================================");
  for (EmployeePojo 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 EmployeePojo object

  Collections.sort(list,new EmployeeDOJComparator());

  // PRINT AFTER SORTED BY AGE
  System.out.println("AFTER SORTED BY DATE OF JOINING");
  System.out.println("===============================================================");
  System.out.println("ID  Name  Salary  Date Of Joining");
  System.out.println("===============================================================");
  for (EmployeePojo 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());
  }
 }
}

Comparable and Comparator interfaces-Part 1
Part-3:Sorting objects with more than one attribute

10 comments:

  1. This is one of popular interview questions and primary advantage of Comparable over Comparator in Java is If any class implement Comparable interface in Java then collection of that object either List or Array can be sorted automatically by using Collections.sort() or Array.sort() method and object will be sorted based on there natural order defined by CompareTo method.

    ReplyDelete
  2. But comparator hsa big advantage. Every time you want to add more attributes for sorting they are added as separate classes whereas in case of Comparable, you need to modify the same compareTO method. So my recommendation is, always let your class implement the Comparable interface for primary key attribute based sorting because that rarely changes, for non-key attributes sorting use comparator as you can add and remove them very easily.

    ReplyDelete
  3. Just what I was looking for, thanks a lot! :)

    ReplyDelete
  4. Suppose I want to sort int[] A = new int[]{2, 5, 6, 1} in descending order. But I don't want to use any Collections like TreeSet or TreeMap. I just want to have one user defined class which implements comparator and sort the elements of array of primitive data type.(e.g. it's not List, it's int[] array). Waiting for your response sir. How would I call this userdefined class from Main class.

    ReplyDelete
  5. In the getter method of array, apply technique that.. convert the array into arraylist, apply sorting and then reconvert it to array..
    This should do the job.

    Other option could be use quick sort implementations available on net and put that in the util class of yours and use it for array sorting.

    ReplyDelete
  6. very useful example..i liked it much

    ReplyDelete
  7. Please also let me know how to sort below form of data based on Date .
    Map m = new HashMap("names","dates);
    how to sort Map m using value field which is a date

    ReplyDelete
  8. I tried using below code..plz guide me

    import java.util.Map;
    import java.util.HashMap;
    import java.util.*;
    import java.text.SimpleDateFormat;
    import java.text.DateFormat;

    public class HashMapEx implements Comparator
    {
    Map data=HashMapEx.getData();
    public static Date d1= new Date(78,10,23);
    public static Date d2 =new Date(81,11,25);
    public static Date d3= new Date(92,01,11);
    public static Date d4 = new Date(11,06,31);
    public static SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");

    public static Map getData()
    {
    HashMap m = new HashMap();
    m.put("a",format.format(d1));
    m.put("B",format.format(d2));
    m.put("C",format.format(d3));
    m.put("i",format.format(d4));

    return m;
    }



    public void display() throws Exception
    {
    System.out.println("Values are...."+data);
    SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy");
    String str = (String)data.get("a");
    Date d=(Date)df.parse(str);
    System.out.println(d);
    }

    public int compare(Object o1,Object o2)
    {
    try{
    SimpleDateFormat newdate1 = new SimpleDateFormat("dd/MM/yyyy");
    SimpleDateFormat newdate2 = new SimpleDateFormat("dd/MM/yyyy");
    Date d1=(Date)newdate1.parse((String)o1);
    Date d2=(Date)newdate1.parse((String)o2);
    System.out.println(d1);


    }catch(Exception e)
    {
    e.printStackTrace();
    }
    if(d1.compareTo(d2) >0)
    return 1;
    else if(d1.compareTo(d2)<0)
    return 0;
    else
    return 1;



    }

    public static void main(String arg[]) throws Exception
    {
    HashMapEx hash = new HashMapEx();
    hash.display();
    SortedMap sortedByValue = new TreeMap(new HashMapEx());
    }
    }

    ReplyDelete
  9. If you are using comparator for sorting objects, use nested static class.

    ReplyDelete