Signup/Sign In
PUBLISHED ON: JULY 23, 2021

Comparator and Comparable in Java

Comparing items with one another is very common and it has a variety of applications. The entire idea of sorting is based on comparing one object with another and deciding which will come first in a sorted collection. The comparator and the comparable are two interfaces that can be implemented by classes to compare their objects. In this tutorial, we will learn more about these interfaces and also look at some of the key differences between the two.

Comparing Objects in Java

Comparable Interface

The Comparable interface is used to compare different objects of a class based on some parameters or criteria. These criteria form the natural ordering for the class.

For example, consider a student class with three fields - name, GPA, and registration number. Now, let's say that we want to compare two students based on their GPA. This natural ordering of the objects based on GPA can be defined by using the Comparable interface.

To compare the objects of a class with each other, the class must implement the Comparable interface. We then need to define the compare strategy by overriding the compareTo() method. The compareTo() method returns an integer value. This value could be positive, negative, or zero based on the following conditions.

  • Positive if the calling object is greater.
  • Negative if the calling object is smaller.
  • 0 if both are equal.

Let's continue with the Student class example and try to compare two student objects based on their GPA. We can simply return the difference in the GPA of the calling student object and the student object taken as a parameter. This will return an integer according to the above conditions. The compareTo() method for this scenario is shown below.

@Override
public int compareTo(Student other)
{
	return (int)(this.getGpa() - other.getGpa());
}

Example: Comparable Interface in Java

Now, let's compare two students using this method. The complete class implementation and the main method are shown below.

class Student implements Comparable<Student>
{
	private String name;
	private int gpa;
	private int regNo;
	
	//Constructor
	public Student(String name, int gpa, int regNo) {
		this.name = name;
		this.gpa = gpa;
		this.regNo = regNo;
	}
	
    //Override the comapareTo() method
	@Override
	public int compareTo(Student other)
	{
		return (int)(this.getGpa() - other.getGpa());//compare using GPA
	}
	
	//getters and setters
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	public int getGpa() {
		return gpa;
	}
	public void setGpa(int gpa) {
		this.gpa = gpa;
	}
	
	public int getRegNo() {
		return regNo;
	}
	public void setRegNo(int regNo) {
		this.regNo = regNo;
	}
}

public class ComparatorComparable
{
	public static void main(String[] args)
	{
		Student s1 = new Student("Justin", 9, 101);
		Student s2 = new Student("Victor", 8, 102);
		
		int comparisonResult = s1.compareTo(s2);
		
		if(comparisonResult > 0)
			System.out.println(s1.getName() + " has higher GPA");
		
		else if(comparisonResult < 0)
			System.out.println(s2.getName() + " has higher GPA");
		
		else
			System.out.println(s1.getName() + " and "+ s2.getName() + " have same GPA");
	}
}


Justin has higher GPA

We will often need to sort a Collection(like ArrayList, or List) of objects into ascending and descending order. The Collections class has a sort() method which internally uses this overridden compareTo() method of the class to compare the objects and then sort them. Let's sort a List of students based on their GPA. The student with the lowest GPA comes first in the sorted list.

import java.util.ArrayList;
import java.util.Collections;

public class ComparatorComparable
{
	public static void main(String[] args)
	{
		Student s1 = new Student("Justin", 9, 101);
		Student s2 = new Student("Victor", 7, 102);
		Student s3 = new Student("Jessica", 8, 103);
		Student s4 = new Student("Paul", 5, 104);
		Student s5 = new Student("Rachel",8, 105);
		
		ArrayList<Student> listOfStudents = new ArrayList<Student>();
		listOfStudents.add(s1);
		listOfStudents.add(s2);
		listOfStudents.add(s3);
		listOfStudents.add(s4);
		listOfStudents.add(s5);
		
		Collections.sort(listOfStudents);
		
		for(Student s : listOfStudents)
			System.out.println(s.getName() + " " + s.getGpa());
	}
}


Paul 5
Victor 7
Jessica 8
Rachel 8
Justin 9

Comparator Interface

The Comparator interface is also used to compare objects of a class based on some parameters. But unlike the Comparable interface, the Comparator interface can be used to create multiple classes to compare objects based on the values of different member variables.

For example, if we wish to sort an array of students based on their registration number, their GPA, and also their names, then we can create three different classes that implement the Comparator interface.

  • Comparable interface, on the other hand, can only create a single compareTo() method which will sort the array based on any one of the members.
  • Sometimes we may not have access to the original class and so we cannot create a compareTo() method according to our needs. In these cases, the Comparator interface proves to be very helpful.
  • To use the Comparator interface, we need to create a separate class that implements this interface. Then, we must override the compare() method of this interface in our class.
  • The compare() method is similar to the compareTo() method of the Comparable interface. It also returns an integer value that follows the same conditions as the compareTo() method.

Example: Comparator Interface in Java

Let's create three different classes that implement the Comparator interface and override the compare() method.

Class for For Student GPA:

class CompareUsingGPA implements Comparator<Student>
{
	@Override
	public int compare(Student s1, Student s2)
	{
		return s1.getGpa() - s2.getGpa();
	}
}

Class for Student Name:

class CompareUsingName implements Comparator<Student>
{
	@Override
	public int compare(Student s1, Student s2)
	{
		return s1.getName().compareTo(s2.getName());//the compareTo() method is already defined
													//for strings so we can directly use it				
	}
}

Class For Student RegNo:

class CompareUsingRegNo implements Comparator<Student>
{
	@Override
	public int compare(Student s1, Student s2)
	{
		return s1.getRegNo() - s2.getRegNo();
	}
}

Let's now sort a student list by using these comparators. The Collections.sort() can take an additional class object that has an overridden compare() method. The sort() method will internally use this compare() method to sort the objects.

public class ComparatorComparable
{
	public static void main(String[] args)
	{
		Student s1 = new Student("Justin", 9, 101);
		Student s2 = new Student("Victor", 7, 102);
		Student s3 = new Student("Jessica", 8, 103);
		Student s4 = new Student("Paul", 5, 104);
		Student s5 = new Student("Rachel",8, 105);
		
		ArrayList<Student> listOfStudents = new ArrayList<Student>();
		listOfStudents.add(s1);
		listOfStudents.add(s2);
		listOfStudents.add(s3);
		listOfStudents.add(s4);
		listOfStudents.add(s5);
		
		System.out.println("Intial unsorted list:");
		for(Student s:listOfStudents)
			System.out.println(s.getName() + " " + s.getRegNo() + " " + s.getGpa());
		
		//Sorting Using GPA
		CompareUsingGPA c1 = new CompareUsingGPA();
		Collections.sort(listOfStudents, c1);
		System.out.println("\nSorting using GPA");

		for(Student s:listOfStudents)
			System.out.println(s.getName() + " " + s.getRegNo() + " " + s.getGpa());
		
		//Sorting Using Names
		CompareUsingName c2 = new CompareUsingName();
		Collections.sort(listOfStudents, c2);
		System.out.println("\nSorting using Name");

		for(Student s:listOfStudents)
			System.out.println(s.getName() + " " + s.getRegNo() + " " + s.getGpa());
			
		//Sorting Using Registration Number
		CompareUsingRegNo c3 = new CompareUsingRegNo();
		Collections.sort(listOfStudents, c3);
		System.out.println("\nSorting using Registration Numbers");

		for(Student s:listOfStudents)
			System.out.println(s.getName() + " " + s.getRegNo() + " " + s.getGpa());		
	}
}


Intial unsorted list:
Justin 101 9
Victor 102 7
Jessica 103 8
Paul 104 5
Rachel 105 8

Sorting using GPA
Paul 104 5
Victor 102 7
Jessica 103 8
Rachel 105 8
Justin 101 9

Sorting using Name
Jessica 103 8
Justin 101 9
Paul 104 5
Rachel 105 8
Victor 102 7

Sorting using Registration Numbers
Justin 101 9
Victor 102 7
Jessica 103 8
Paul 104 5
Rachel 105 8

Summary

Comparable and Comparator interfaces are used to compare objects of a class. The Comparable interface is used to set a natural ordering pattern for the class. The Comparator interface is used when we need multiple ways of comparing objects. Comparator is also useful when we don't have access to the original class.



About the author:
I am a 3rd-year Computer Science Engineering student at Vellore Institute of Technology. I like to play around with new technologies and love to code.