Java Comparator Interface – Working of Collections.Sort()

When we work with user-defined classes in Java, there may have been some kind of a need to arrange data in a proper way. However since the data is user-defined, there is absolutely no way for inbuilt functions to arrange these elements. Moreover, if there is a specific condition for arranging these data, then we need to have a different method inside the class. To avoid these kinds of problems, Java has an interface known as the Comparator Interface.

Java Comparator Interface

Don't become Obsolete & get a Pink Slip
Follow DataFlair on Google News & Stay ahead of the game

Comparator Interface in Java

When you need to order the data items of a user-defined data, i.e, classes, then you can use the comparator interface. It can prove to be fruitful when you need a data item based on a specific condition that would differ from user to user.

There are two primary methods in the Java Comparator Interface:

  1. public int compare(Object ob1, Object b2 ) – This function has the responsibility of comparing any two objects and returns an integer value based on it. This method returns -1,0,1 to say that it is either less than, equal to, or greater than the other object.
  2. public boolean equals(Object obj) – This method is particularly useful for checking whether the current object is exactly equal to the second object.
  3. static <T> Comparator<T> nullsFirst(Comparator<? super T> comparator) – This function essentially compares objects. However, it takes into consideration that nulls are lesser than non-null elements.
  4. static <T> Comparator<T> nullsLast(Comparator<? super T> comparator) – This is similar to the nullsLast comparator except for a fundamental difference. This method takes into consideration that nulls are greater than non-null elements in the collection.

How does the Sort Method in the Collection Sort Work?

  • Whenever we need to sort the values in a collection, this “sort” method transfers control to the compare method in the class.
  • The compare method then returns some values based on the comparison.
  • It returns 0 if both the objects are equal.
  • This returns 1 if the first object is greater than the second.
  • It returns -1 if the second object is greater than the first.
  • Using these values the function decides whether to swap the values for the sorting process.

Java program to illustrate the use of Comparator Interface(Old Style – Without generics):

package com.dataflair.comparatorinterface;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

class Cars

{
    //this is the class that defines the properties of a car object.
    //The car would have a name. A type. and an ID. 
    String name;
    String type;
    long ID;

    Cars(String name, String type, long ID)
    {
        this.name=name;
        this.type=type;
        this.ID=ID;
    }
}
class NameComparator implements Comparator
{

    @Override
    public int compare(Object o1, Object o2) {
        // TODO Auto-generated method stub
        Cars c2=(Cars)o2;
        Cars c1=(Cars)o1;
        return c1.name.compareTo(c2.name);
    }
}
class TypeComparator implements Comparator
{
    @Override
    public int compare(Object o1, Object o2)
    {
        Cars c2=(Cars)o2;
        Cars c1=(Cars)o1;
        return c1.type.compareTo(c2.type);
    }
}

public class Base {
    public static void main(String[] args) {

        List<Cars> carslist = new ArrayList<>();
        carslist.add(new Cars("Viper","Sports",1125412342l));
        carslist.add(new Cars("Supra","Sports",1244560087l));
        carslist.add(new Cars("Royce","Sedan",1111412341l));
        carslist.add(new Cars("Patriot","OffRoad",9831441244l));

        System.out.println("The cars before sorting\n\n");
        carslist.forEach((car)->System.out.println(car.name+" "+car.type+" "+car.ID));

        //Now we sort by the name
        Collections.sort(carslist, new NameComparator());

        System.out.println("\n\nThe cars after sorting by the car names\n\n");
        carslist.forEach((car)->System.out.println(car.name+" "+car.type+" "+car.ID));

        System.out.println("\n\nThe cars after sorting them by their type\n\n");

        //Now we sort the values by their type. 
        Collections.sort(carslist,new TypeComparator());

        carslist.forEach((car)->System.out.println(car.name+" "+car.type+" "+car.ID));
        
    }
    
}

Output:

The cars before sortingViper Sports 1125412342
Supra Sports 1244560087
Royce Sedan 1111412341
Patriot OffRoad 9831441244

The cars after sorting by the car names

Patriot OffRoad 9831441244
Royce Sedan 1111412341
Supra Sports 1244560087
Viper Sports 1125412342

The cars after sorting them by their type

Patriot OffRoad 9831441244
Royce Sedan 1111412341
Supra Sports 1244560087
Viper Sports 1125412342

Java program to illustrate the use of Comparator Interface(New style- With generics):

package com.dataflair.comparatorinterface;
import java.util.*;


public class Human
{
    String name;
    int age;
    Human()
    {
        name="NoName";
        age=0;
    }
    Human(String name, int age)
    {
        this.name=name;
        this.age=age;

    }
    public String getName() {
        return name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public void setName(String name) {
        this.name = name;    
    }

    public static Comparator<Human> ageComparator=new Comparator<Human>()
    {
        public int compare(Human h1, Human h2)
        {
            return h1.getAge()-h2.getAge();
        }
    };

    public static Comparator<Human> nameComparator=new Comparator<Human>()
    {
        public int compare(Human h1, Human h2)
        {
            return h1.getName().compareTo(h2.getName());
        }
    };

public static void main(String[] args) {
    ArrayList<Human> humans = new ArrayList<>();
    humans.add(new Human("Shraman", 21));
    humans.add(new Human("Shubham", 23));
    humans.add(new Human("Pranav", 20));
    humans.add(new Human("Srijan", 19));
    humans.add(new Human("Gourav", 24));
    humans.add(new Human("Amit", 11));
    humans.add(new Human("Raju", 41));

    System.out.println("Before sorting");
    humans.forEach((n)-> System.out.print(n.name+" "+n.age+" \n"));

    System.out.println("\n After Sorting by age");
    Collections.sort(humans, ageComparator );
    humans.forEach((n)-> System.out.print(n.name+" "+n.age+" \n"));

    System.out.println("\n After sorting by Name");
    
    Collections.sort(humans, nameComparator );
    humans.forEach((n)-> System.out.print(n.name+" "+n.age+" \n"));
}

}

Output:

Before sorting
Shraman 21
Shubham 23
Pranav 20
Srijan 19
Gourav 24
Amit 11
Raju 41After Sorting by age
Amit 11
Srijan 19
Pranav 20
Shraman 21
Shubham 23
Gourav 24
Raju 41

After sorting by Name
Amit 11
Gourav 24
Pranav 20
Raju 41
Shraman 21
Shubham 23
Srijan 19

As we can observe, the comparator method is an easier method of arranging the data items according to a particular logic. Point to note is that this example corresponds to the new way of using Java generics to implement individual comparators for.

Basic Differences between Comparable and Comparator in Java

  1. The comparable interface can only be useful for sorting the elements in a class in a single way. However, the comparator interface is useful for sorting multiple types of data in a class.
  2. While using comparable Interfaces, the class itself has to implement the interface. However, we may choose to implement or not implement the Comparator interface in the base class. You can take advantage of anonymous classes in Java to leverage this issue.
  3. While using the Comparable interface, we do not need to make any changes to the code. This is because the sort functions of the collections class automatically use the compareTo method in the class. However, while we implement the Comparator interface, we need to use the comparator name along with the sort function.
  4. The java.lang houses the Comparable interface whereas the java. util package contains the Comparator interface. You have to be cautious while using interfaces because you would run into errors if you do not import the correct package.

Rules for Using Comparator Interface

There are certain rules that you should keep in mind before actually attempting to implement an interface. Some of them are:

  • You can use the Comparator interface to sort the elements of the collection.
  • If you keep your object type as undefined while implementing the Comparator Interface, then you need to make sure that you typecast all the variables inside it to the Object inside the method.
  • You need to specify the generic of the user datatype while passing it to a comparator. If you do not then java converts it to an Object type by default. You would not be able to compare individual elements after that.

Summary

In this article, we came to know about the various uses of the comparator interface. We also came to know about the process of using Comparator Interfaces in programs to structure classes easily. We now know comparable interface and comparator interface, and how they are different from each other. This is a very popular question in interviews.

Leave a Reply

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

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.