Difference between Comparable and Comparator

Reading Time: 6 minutes

Hello readers today in this blog I’m going to explain the fundamental concept of Comparable and Comparator along with there differences. But before going to this topic we must have basic knowledge of Generics. So without explaining details theoretical concept let’s see through example, why we need Generics ?

let’s see an example where we want to display the value of array:

public class Demo {
    public static void main(String[] args) {
        Integer[] arri={10,90,30,40,20};
        bubbleSort(arri);
        display(arri);
        String[] arrs={"Hello","Shivam","Harsh","Gopal","Gaurav"};
        display(arrs);
      
        }

    public static void display(Integer[]arr){
        for(Integer val : arr){
            System.out.print(val+" ");
        }
        System.out.println();
    }
    public static void display(String[]arr){
        for(String val : arr){
            System.out.print(val+" ");
        }
       System.out.println();
   }

Output:
10 90 30 40 20 
Hello Shivam Harsh Gopal Gaurav 

Why we need Generics?

I have taken two array one is array of Integers arri and other is array of Strings arrs in order to display both the array arri and arrs we need to overload display function. suppose we have another array which is containing car type objects and we want to display it. so what we can do ?

The first and very simple answer is overload display function again which takes arguments of car type objects.

Well it will work fine but it is not perfect solution the reason is If display function will get another type of object we have to overload again display function and hence it becomes never ending process. Which is nothing but repetition of code and that is not good in development, and here Generics comes in action.

Here is generic display function:

class Car{
    int speed;
    int price;
    String color;
    public Car(   int speed,int price,String color){
        this.speed=speed;
        this.price=price;
        this.color=color;
    }
    @Override
    public String toString(){
        return "s = "+this.speed+" p = "+this.price+" c = "+this.color+"; ";
    }
}

public class Demo {
    public static void main(String[] args) {
        Integer[] arri={10,90,30,40,20};
        display(arri);
        String[] arrs={"Hello","Shivam","Harsh","Gopal","Gaurav"};
        display(arrs);
        Car[] cars = new Car[5];
        cars[0]= new Car(1000,100,"red");
        cars[1]= new Car(4000,600,"green");
        cars[2]= new Car(2000,300,"blue");
        cars[3]= new Car(3000,200,"black");
        cars[4]= new Car(6000,400,"white");
        bubbleSort(cars);
        display(cars);
        }


    public static <T> void display(T[]arr){
        for(T val : arr){
            System.out.println(val+" ");
        }
        System.out.println();
    }

}
output:

10 
90 
30 
40 
20 

Hello 
Shivam 
Harsh 
Gopal 
Gaurav 

s = 1000 p = 100 c = red;  
s = 4000 p = 600 c = green;  
s = 2000 p = 300 c = blue;  
s = 3000 p = 200 c = black;  
s = 6000 p = 400 c = white;  

As we can see that one Generic display function is enough to display all type of objects.

To make function generic we have to specify type parameter in angular bracket (like <T>) before return type. Like functions we can also make generic classes and interfaces. But that is beyond the topic.

Note:

Object class is parent class of every class and every class extends Object class.Inside Object Class there is toString() method on which print method is dependent. If you see in above example Inside Car class we have override toString() method If you will try to print car[index] without overriding toString() method it will print address of the reference not the actual value. So we have override this method.

Now let’s see what is Comparable and Comparator and why we need this ?

So in java there are two interfaces to sort the object on the basis of data members.

  • Comparable
  • Comparator

For an example If we want to sort Car class object on the basis of there speed,price and color. Then it will be not possible without using Comparable and Comparator interface.

Here is Car class which are implementing Comparable interface, so it have to provide body for its compareTo() function where we have write logic to sort the object on the basis of there speed.

public class Car implements Comparable<Car> {
    int speed;
    int price;
    String color;
    public Car(   int speed,int price,String color){
        this.speed=speed;
        this.price=price;
        this.color=color;
    }
    @Override
    public String toString(){
        return "s = "+this.speed+" p = "+this.price+" c = "+this.color+"; ";
    }

    @Override
    public int compareTo(Car other) {
        return this.speed-other.speed;
    }
}
public class Demo {
    public static void main(String[] args) {

        Car[] cars = new Car[5];
        cars[0]= new Car(1000,100,"red");
        cars[1]= new Car(4000,600,"green");
        cars[2]= new Car(2000,300,"blue");
        cars[3]= new Car(3000,200,"black");
        cars[4]= new Car(6000,400,"white");
        bubbleSort(cars);
        display(cars);
        }



    public static <T> void display(T[]arr){
        for(T val : arr){
            System.out.println(val+" ");
        }
        System.out.println();
    }

    public static<T extends Comparable<T>> void bubbleSort(T[]arr){
        for(int counter=0;counter<arr.length-1;counter++){
            for(int j=0;j< arr.length-1-counter;j++){
                if (arr[j].compareTo(arr[j+1])>0){
                    T temp=arr[j];
                    arr[j]=arr[j+1];
                    arr[j+1]=temp;
                }
            }
        }
    }
}
output(sorted on the basis of speed).
s = 1000 p = 100 c = red;  
s = 2000 p = 300 c = blue;  
s = 3000 p = 200 c = black;  
s = 4000 p = 600 c = green;  
s = 6000 p = 400 c = white; 

Inside Main class in bubbleSort() where we have declare it generic(in angular bracket <>) there we also need to specify that it is extending Comparable which means in bubble sort only that parameter will be passed whose logic have been written in compareTo() function,which is speed here.

If you want to sort on other parameter like price and color then you just need to change in compareTo() function.

Sorted on the behalf of price :

public class Car implements Comparable<Car> {
    int speed;
    int price;
    String color;
    public Car(   int speed,int price,String color){
        this.speed=speed;
        this.price=price;
        this.color=color;
    }
    @Override
    public String toString(){
        return "s = "+this.speed+" p = "+this.price+" c = "+this.color+"; ";
    }

    @Override
    public int compareTo(Car other) {
        return other.price-this.price;
    }
}
public class Demo {
    public static void main(String[] args) {

        Car[] cars = new Car[5];
        cars[0]= new Car(1000,100,"red");
        cars[1]= new Car(4000,600,"green");
        cars[2]= new Car(2000,300,"blue");
        cars[3]= new Car(3000,200,"black");
        cars[4]= new Car(6000,400,"white");
        bubbleSort(cars);
        display(cars);
        }



    public static <T> void display(T[]arr){
        for(T val : arr){
            System.out.println(val+" ");
        }
        System.out.println();
    }

    public static<T extends Comparable<T>> void bubbleSort(T[]arr){
        for(int counter=0;counter<arr.length-1;counter++){
            for(int j=0;j< arr.length-1-counter;j++){
                if (arr[j].compareTo(arr[j+1])>0){
                    T temp=arr[j];
                    arr[j]=arr[j+1];
                    arr[j+1]=temp;
                }
            }
        }
    }
}
output
s = 4000 p = 600 c = green;  
s = 6000 p = 400 c = white;  
s = 2000 p = 300 c = blue;  
s = 3000 p = 200 c = black;  
s = 1000 p = 100 c = red;  

Sorted on the behalf of color :

public class Car implements Comparable<Car> {
    int speed;
    int price;
    String color;
    public Car(   int speed,int price,String color){
        this.speed=speed;
        this.price=price;
        this.color=color;
    }
    @Override
    public String toString(){
        return "s = "+this.speed+" p = "+this.price+" c = "+this.color+"; ";
    }

    @Override
    public int compareTo(Car other) {
        return other.price-this.price;
    }
}
public class Demo {
    public static void main(String[] args) {

        Car[] cars = new Car[5];
        cars[0]= new Car(1000,100,"red");
        cars[1]= new Car(4000,600,"green");
        cars[2]= new Car(2000,300,"blue");
        cars[3]= new Car(3000,200,"black");
        cars[4]= new Car(6000,400,"white");
        bubbleSort(cars);
        display(cars);
        }



    public static <T> void display(T[]arr){
        for(T val : arr){
            System.out.println(val+" ");
        }
        System.out.println();
    }

    public static<T extends Comparable<T>> void bubbleSort(T[]arr){
        for(int counter=0;counter<arr.length-1;counter++){
            for(int j=0;j< arr.length-1-counter;j++){
                if (arr[j].compareTo(arr[j+1])>0){
                    T temp=arr[j];
                    arr[j]=arr[j+1];
                    arr[j+1]=temp;
                }
            }
        }
    }
}

output:
s = 3000 p = 200 c = black;  
s = 2000 p = 300 c = blue;  
s = 4000 p = 600 c = green;  
s = 1000 p = 100 c = red;  
s = 6000 p = 400 c = white;  

Now we have seen how Comparable interface works. We should use comparable interface in that class for which we want to define natural ordering for it’s object. Like if you want that object of Car class always should be sorted on behalf of Price,speed or color then you should use Comparable.

In Comparable interface Once you have decided parameter for sorting you can not sort them on behalf of other parameter. Which is big drawback in case of Comparable and hence Comparator comes in action.

Let’s see through example how the Comparator is solving this problem.

class Car {
    int speed;
    int price;
    String color;
    public Car(int speed,int price,String color){
        this.speed=speed;
        this.price=price;
        this.color=color;
    }
    @Override
    public String toString(){
        return "s = "+this.speed+" p = "+this.price+" c = "+this.color+"; ";
    }

}

class CarSpeedComparator implements Comparator<Car> {

    @Override
    public int compare(Car tcar,Car ocar){
        return tcar.speed-ocar.speed;
    }
}

class CarPriceComparator implements Comparator<Car> {
    @Override
    public int compare(Car tcar,Car ocar){
        return ocar.price-tcar.price;
    }
}

class CarColorComparator implements Comparator<Car> {
    @Override
    public int compare(Car tcar,Car ocar){
        return tcar.color.compareTo(ocar.color);
    }
}

public class Demo {
    public static void main(String[] args) {
        Car[] cars = new Car[5];
        cars[0]= new Car(1000,100,"red");
        cars[1]= new Car(4000,600,"green");
        cars[2]= new Car(2000,300,"blue");
        cars[3]= new Car(3000,200,"black");
        cars[4]= new Car(6000,400,"white");

        System.out.println("sorted on the behalf of speed:");
        bubbleSort(cars,new CarSpeedComparator());
        display(cars);
        System.out.println("sorted on the behalf of price:");
        bubbleSort(cars,new CarPriceComparator());
        display(cars);
        System.out.println("sorted on the behalf of color:");
        bubbleSort(cars,new CarColorComparator());
        display(cars);
    }

    public static <T> void display(T[]arr){
        for(T val : arr){
            System.out.println(val+" ");
        }
        System.out.println();
    }
    public static<T> void bubbleSort(T[]arr,Comparator<T>comparator){
        for(int counter=0;counter<arr.length-1;counter++){
            for(int j=0;j< arr.length-1-counter;j++){
                if (comparator.compare(arr[j],arr[j+1])>0){
                    T temp=arr[j];
                    arr[j]=arr[j+1];
                    arr[j+1]=temp;
                }
            }
        }
    }
}


output:
sorted on the behalf of speed:
s = 1000 p = 100 c = red;  
s = 2000 p = 300 c = blue;  
s = 3000 p = 200 c = black;  
s = 4000 p = 600 c = green;  
s = 6000 p = 400 c = white;  

sorted on the behalf of price:
s = 4000 p = 600 c = green;  
s = 6000 p = 400 c = white;  
s = 2000 p = 300 c = blue;  
s = 3000 p = 200 c = black;  
s = 1000 p = 100 c = red;  

sorted on the behalf of color:
s = 3000 p = 200 c = black;  
s = 2000 p = 300 c = blue;  
s = 4000 p = 600 c = green;  
s = 1000 p = 100 c = red;  
s = 6000 p = 400 c = white;  



Here you can see that by using Comparator we have Choice of parameter to sort the objects, even we can sort the objects on behalf of all parameter at the same time.

That’s all for this blog I am providing some reference for more details please feel free to check it out.

Written by 

I'm a Software Consultant at Knoldus . I have completed my B.tech in Computer Science stream from IMS Engineering College, Ghaziabad. I love to explore new technologies and have great interest in problem solving.