Comparator and Comparable interfaces in Java


c4c3

Comparator and Comparable interfaces are heavily used in the Java development to manage the sorting of the collections. This approach will achieve the software engineering goals such as extensibility, reusability, modularity etc. In this post I like to explain this mechanism of how to use comparator and comparable interfaces. First thing is we are going to use the Collections API for sorting which is provided by Java. So we have to expose sorting comparison logic without exposing the internal structure of our custom implementation.Here you can download the source.

Lets look at how to use Comparable interface.

As an example I have Employee class which is created by me and need to sort the collection of employees according to the employee age.

  • First we need to implement the Comparable interface in Employee class and override the compareTo method
  • Then we can pass the employee collection to the Collections.sort() API to do the sorting.
  • Underneath what will happen Collections.sort() method will access the compareTo implementation and get the decision according to the return value.

See the code sample below to get clear understanding.

package sample.common;

/**
 * Employee Class
 *
 * @author malalanayake
 *
 */
public class Employee implements Comparable<Employee> {
	private int id;
	private String name;
	private int age;
	private int salary;

	public Employee(int id, String name, int age, int salary) {
		this.id = id;
		this.name = name;
		this.age = age;
		this.salary = salary;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public int getSalary() {
		return salary;
	}

	public void setSalary(int salary) {
		this.salary = salary;
	}

	public int compareTo(Employee o) {
		if (o.getAge() == this.age) {
			return 0;
		} else if (o.getAge() > this.age) {
			return -1;
		} else {
			return 1;
		}
	}

	@Override
	public String toString() {
		return "[Employee ID:" + this.getId() + " Name:" + this.getName()
				+ " Age:" + this.getAge() + " Salary:" + this.getSalary() + "]";
	}

}
package sample.app;

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

import comparator.sample.app.SalaryComparator;
import sample.common.Employee;

/**
 * Application Class
 *
 * @author malalanayake
 *
 */
public class App {
	public static void main(String[] args) {
		List<Employee> employees = new ArrayList<Employee>();

		Employee emp_dinuka = new Employee(101, "Dinuka", 27, 95000);
		employees.add(emp_dinuka);

		Employee emp_malalanayake = new Employee(100, "Malalanayake", 27, 85000);
		employees.add(emp_malalanayake);

		Employee emp_Thanuja = new Employee(305, "Thanuja", 23, 150000);
		employees.add(emp_Thanuja);

		Employee emp_Damith = new Employee(204, "Damith", 20, 75000);
		employees.add(emp_Damith);

		System.out.println("=======Before Sorting=====");
		for (Employee emp : employees) {
			System.out.println(emp.toString());
		}

		Collections.sort(employees);
		System.out.println("=======After Sorting=====");
		for (Employee emp : employees) {
			System.out.println(emp.toString());
		}
	}
}

You can see in the above case we can have only one sorting logic over the employee class. Lets think about sometimes if I need to sort the Employee by their salaries and sometimes I need to sort by their age. Then you can see we don’t have space to put that logic in my Employee class because already I have method implementation according to the age. In this kind of situation Comparator comes to the picture to solve the problem.

Lets look at how to use Comparator

  • So first you have to have comparator implementation class. In above case I have created SalaryComparator class which is provide the salary comparison.
  • Then you can pass the employee collection to overloaded method in collections api to sort the given collection according to the given comparator.
package comparator.sample.app;

import java.util.Comparator;

import sample.common.Employee;

/**
 * Salary Comparator
 *
 * @author malalanayake
 *
 */
public class SalaryComparator implements Comparator<Employee> {

	public int compare(Employee o1, Employee o2) {
		if (o1.getSalary() > o2.getSalary()) {
			return 1;
		}

		if (o1.getSalary() < o2.getSalary()) {
			return -1;
		}
		return 0;
	}

}
package sample.app;

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

import comparator.sample.app.SalaryComparator;
import sample.common.Employee;

/**
 * Application Class
 *
 * @author malalanayake
 *
 */
public class App {
	public static void main(String[] args) {
		List<Employee> employees = new ArrayList<Employee>();

		Employee emp_dinuka = new Employee(101, "Dinuka", 27, 95000);
		employees.add(emp_dinuka);

		Employee emp_malalanayake = new Employee(100, "Malalanayake", 27, 85000);
		employees.add(emp_malalanayake);

		Employee emp_Thanuja = new Employee(305, "Thanuja", 23, 150000);
		employees.add(emp_Thanuja);

		Employee emp_Damith = new Employee(204, "Damith", 20, 75000);
		employees.add(emp_Damith);

		SalaryComparator comparator = new SalaryComparator();
		Collections.sort(employees, comparator);
		System.out.println("=======After Sorting By Salary=====");
		for (Employee emp : employees) {
			System.out.println(emp.toString());
		}
	}
}

So If you have multiple sorting logics then you have to go for the Comparator because then only you can have multiple logics. Otherwise you can encapsulate the logic inside your custom implementation class by using the Comparable interface. I hope you got the idea of how to use the comparator and comparable interfaces.

Leave a comment

Blog at WordPress.com.

Up ↑