Comparing user defined objects : Comparable and Comparator


Comparison plays important role in any programming language. Almost all the sorting techniques involves comparison. In Java, all the predefined classes and primitive data types supports comparison. User defined data types needs to provide the comparison logic, Comparable and Comparator comes in picture. For the primitive data type, how to compare is inbuilt and can be achieved using different comparison operators like <, >, <=, >=. Assume int a = 10 and int b = 20, then a<b is true. Consider a class Student, comparing it using < is not possible as it is not a primitive data type. Student class have some method that helps in comparing two student object. Java provides an interface called Comparable which needs to be implemented by class that provides comparison logic. Comparable interface have one method compareTo which takes Object as an argument. Consider a following code with class Employee and array of object.

import java.util.Arrays;
class Employee
{
	private int eid;
	private String name;
	private String dept;
	private int salary;
	public Employee(int eid, String name, String dept, int salary)
	{
		this.eid = eid;
		this.name = name;
		this.dept = dept;
		this.salary = salary;
	}
	public String toString()
	{
		return "id : " + eid + " Name : " + name + 
			" Department : " + dept + " Salary : " + salary;
	}

}
class Test
{
	public static void main(String args[])
	{
		Employee [] employee = new Employee[5];
		employee[0] = new Employee(1, "ABC", "Purchase" , 30000);
		employee[1] = new Employee(2, "XYZ", "Sales" , 15000);
		employee[2] = new Employee(3, "DEF", "Account" , 50000);
		employee[3] = new Employee(4, "PQR", "Sales" , 20000);
		employee[4] = new Employee(5, "MNO", "Purchase" , 10000);
		System.out.println(Arrays.toString(employee));
	}
}

 Compiling and executing the program will give

D:\>javac Test.java

D:\>java Test
[id : 1 Name : ABC Department : Purchase Salary : 30000, id : 2 Name : XYZ Department : Sales Salary : 15000, id : 3 Name : DEF Department : Account Salary : 50000, id : 4 Name : PQR Department : Sales Salary : 20000, id : 5 Name : MNO Department : Purchase Salary : 10000]

In Java, Arrays have many methods [ link to previous post ] of which one is sort method used to sort the array. If it have been an int array sorting is very simple i.e arranging the elements in the ascending order. Questions arises is how to arrange the employee array means should it be in order of name, department or salaries or all of them ? It seems that user defined classes or data types have choices, and in that case it is required to pick a default mechanism out of from all available option. Lets say salary to be treated as default way or natural way of ordering the employee array. In Java, one need to implement Comparable interface and override the compareTo method in the class to instruct Java that this class is Comparable and can participate in sorting. compareTo method looks like

public int compareTo(Object o)

It returns int which means

  • 0 means the invoking object and object passed as an argument are equals.
  • +ve means that invoking object is greated than object passed as an argument.
  • -ve means that invoking object is smaller thant object passed as an argument.

So e[0].compareTo(e[1]) returns int and solves the comparision problem

Following code shows the Comparable and sorting of array

import java.util.Arrays;
class Employee implements Comparable
{
	private int eid;
	private String name;
	private String dept;
	private int salary;
	public Employee(int eid, String name, String dept, int salary)
	{
		this.eid = eid;
		this.name = name;
		this.dept = dept;
		this.salary = salary;
	}
	public String toString()
	{
		return "id : " + eid + " Name : " + name + 
			" Department : " + dept + " Salary : " + salary;
	}
	public int compareTo(Employee t)
	{
		return this.salary - t.salary;
	}

}
class Test
{
	public static void main(String args[])
	{
		Employee [] employee = new Employee[5];
		employee[0] = new Employee(1, "ABC", "Purchase" , 30000);
		employee[1] = new Employee(2, "XYZ", "Sales" , 15000);
		employee[2] = new Employee(3, "DEF", "Account" , 50000);
		employee[3] = new Employee(4, "PQR", "Sales" , 20000);
		employee[4] = new Employee(5, "MNO", "Purchase" , 10000);
		System.out.println(Arrays.toString(employee));
		Arrays.sort(employee);
		System.out.println(Arrays.toString(employee));
	}
}


D:\>javac Test.java

D:\>java Test

[id : 1 Name : ABC Department : Purchase Salary : 30000, id : 2 Name : XYZ Department : Sales Salary : 15000, id : 3 Name : DEF Department : Account Salary : 50000, id : 4 Name : PQR Department : Sales Salary : 20000, id : 5 Name : MNO Department : Purchase Salary : 10000]

[id : 5 Name : MNO Department : Purchase Salary : 10000, id : 2 Name : XYZ Department : Sales Salary : 15000, id : 4 Name : PQR Department : Sales Salary : 20000, id : 1 Name : ABC Department : Purchase Salary : 30000, id : 3 Name : DEF Department : Account Salary : 50000]

Now what if there is need to sort the employee on name or department. In such case comparator interface is used to provide additional way of comparing the objects. It is same as Comparable, except it have method compare with two arguments. Following code demonstrate the use of Comparable on Name

import java.util.Arrays;
import java.util.Comparator;
class NameComprator implements Comparator
{
	public int compare(Employee a, Employee b)
	{
		return a.getName().compareTo(b.getName());
	}
}
class Employee implements Comparable
{
	private int eid;
	private String name;
	private String dept;
	private int salary;
	public Employee(int eid, String name, String dept, int salary)
	{
		this.eid = eid;
		this.name = name;
		this.dept = dept;
		this.salary = salary;
	}
	public String toString()
	{
		return "id : " + eid + " Name : " + name + 
			" Department : " + dept + " Salary : " + salary;
	}
	public int compareTo(Employee t)
	{
		return this.salary - t.salary;
	}
	public String getName()
	{
		return name;
	}

}
class Test
{
	public static void main(String args[])
	{
		Employee [] employee = new Employee[5];
		employee[0] = new Employee(1, "ABC", "Purchase" , 30000);
		employee[1] = new Employee(2, "XYZ", "Sales" , 15000);
		employee[2] = new Employee(3, "DEF", "Account" , 50000);
		employee[3] = new Employee(4, "PQR", "Sales" , 20000);
		employee[4] = new Employee(5, "MNO", "Purchase" , 10000);
		System.out.println(Arrays.toString(employee));
		Arrays.sort(employee);
		System.out.println(Arrays.toString(employee));
		Arrays.sort(employee, new NameComprator());
		System.out.println(Arrays.toString(employee));
	}
}

D:\>javac Test.java

D:\>java Test
[id : 1 Name : ABC Department : Purchase Salary : 30000, id : 2 Name : XYZ Department : Sales Salary : 15000, id : 3 Name : DEF Department : Account Salary : 50000, id : 4 Name : PQR Department : Sales Salary : 20000, id : 5 Name : MNO Department : Purchase Salary : 10000]

[id : 5 Name : MNO Department : Purchase Salary : 10000, id : 2 Name : XYZ Department : Sales Salary : 15000, id : 4 Name : PQR Department : Sales Salary : 20000, id : 1 Name : ABC Department : Purchase Salary : 30000, id : 3 Name : DEF Department : Account Salary : 50000]

[id : 1 Name : ABC Department : Purchase Salary : 30000, id : 3 Name : DEF Department : Account Salary : 50000, id : 5 Name : MNO Department : Purchase Salary : 10000, id : 4 Name : PQR Department : Sales Salary : 20000, id : 2 Name : XYZ Department : Sales Salary : 15000]

In sorting, provide the comparator to avoid natural or default ordering.

So using Comparable and Comparator user defined classes can participate in different ways of sorting and can help in comparing the objects.

Leave a comment

Your email address will not be published. Required fields are marked *