Comparable(I) interface:

It is present in java.lang package and it contains only one method compareTo().

public int compareTo(Object o)
obj1.compareTo(obj2)

For Examplei>

returns -ve --> obj1 has to come before obj2
returns +ve --> obj1 has to come after obj2
returns -ve --> obj1 and obj2 are equal


class ComparableDemo{
    public static void main(String[] args){
        System.out.println("A".compareTo("Z"));
        System.out.println("S".compareTo("K"));
        System.out.println("K".compareTo("K"));
        System.out.println("K".compareTo(null));
    }
}

Output:
-25
8
0

Exception in thread "main" java.lang.NullPointerException: Cannot read field "value" because "anotherString" is null
at java.base/java.lang.String.compareTo(String.java:1215) at ComparableDemo.main(ComparableDemo.java:6)
Comparable

Note: If default natural sorting order not available or if we are not satisfied default natural sorting order then we can go for customized sorting by using Comparator.
Comparable meant for default natural sorting order whereas Comparable meant for customized sorting order.

Comparator(I) interface:

Comparator present in java.util package and it defines two methods
compare() and equals()

public int compare(Object obj1, Object obj2)

For Example
compare(obj1, obj2)
returns -ve --> obj1 has to come before obj2
returns +ve --> obj1 has to come after obj2
returns -ve --> obj1 and obj2 are equal
public boolean equals(Object obj)

whenever we are implementing Comparator interface compulsory we should provide implementation only for compare() method and we are not required to provide implementation for equals() method because it is already available to our class from Object class through inheritance.


write a program to insert integer objects into the TreeSet where the sorting order is descending order.

import java.util.*;
class TreeSetDemo{
    public static void main(String[] args){
        TreeSet<Integerts = new TreeSet<Integer>(new MyComparator()); //line-1
        ts.add(10);
        ts.add(0);
        ts.add(15);
        ts.add(5);
        ts.add(20);
        ts.add(20);
        System.out.println(ts);
    }
}
class MyComparator implements Comparator<Object>{
    public int compare(Object obj1Object obj2){
        Integer I1 = (Integer)obj1;
        Integer I2 = (Integer)obj2;
        if(I1 < I2){
            return +1;
        }
        else if(I1 > I2){
            return -1;
        }
        else{
            return 0;
        }
    }
}

Output:
[20, 15, 10, 5, 0]

At line-1 if we are not passing Comparator object then internally JVM will call compare To() method which is meant for default natural sorting order. In this case the output is 0, 5, 10, 15, 20
At line-1 if we are passing Comparator object then JVM will call compare() method which is meant for customized sorting order. In this case the output is 20, 15, 10, 5, 0

Comparator Diagram

Various possible implementation of compare() method:

public int compare(Object obj1, Object obj2){
    Integer I1 = (Integer)obj1;
    Integer I2 = (Integer)obj2;
    return I1.compareTo(I2); //DefaultNaturalSortingOrder(AscendingOrder)[0,5,10,15,20]
    return -I1.compareTo(I2); //(DescendingOrder)[20, 15, 10, 5, 0]
    return I2.compareTo(I1); //(DescendingOrder)[20, 15, 10, 5, 0]
    return -I2.compareTo(I1); //(AscendingOrder)[0, 5, 10, 15, 20]
    return +1//(InsertionOrder)[10, 0, 15, 5, 20, 20]
    return -1//(Reverse of InsertionOrder)[20, 20, 5, 15, 0, 10]
    return 0//(Only first elem will be inserted and all remaining are duplicates) [10]
}

Write a program to insert String objects into the TreeSet where all elements should be inserted according reverse of alphabetical order.

import java.util.*;
class TreeSetDemo{
    public static void main(String[] args){
        TreeSet<Stringts = new TreeSet<String>(new MyComparator()); //line-1
        ts.add("Tammanah");
        ts.add("Samanta");
        ts.add("Anupama");
        ts.add("PoojaHedge");
        ts.add("Anushka");
        System.out.println(ts);
    }
}
class MyComparator implements Comparator<Object>{
    public int compare(Object obj1Object obj2){
        String s1 = obj1.toString();
        String s2 = (String)obj2;
        return s2.compareTo(s1);
        //return -s2.compareTo(s2);
    }
}

Output:
[Tammanah, Samanta, PoojaHedge, Anushka, Anupama]

Write a program to insert StringBuffer objects into the TreeSet where sorting order is alphabetical order.

import java.util.*;
class TreeSetDemo{
    public static void main(String[] args){
        TreeSet t = new TreeSet(new MyComparator());
        t.add(new StringBuffer("PK"));
        t.add(new StringBuffer("Prabhas"));
        t.add(new StringBuffer("NTR"));
        t.add(new StringBuffer("RC"));
        System.out.println(t);
    }
}
class MyComparator implements Comparator{
    public int compare(Object obj1Object obj2){
        String s1 = obj1.toString();
        String s2 = obj2.toString();
        return s1.compareTo(s2);
    }
}

Output:
[NTR, PK, Prabhas, RC]
Note: If we are depending on default natural sorting order compulsory objects should be homogeneous and Comparable otherwise, we will get runtime exception saying ClassCastException.
If we are defining our own sorting by Comparator then objects need not be Comparable and homogeneous i.e., we can add heterogeneous non comparable objects also.

Write a program to insert String and StringBuffer objects into TreeSet where sorting order is increasing length order. If two objects having same length then consider their alphabetical order.

import java.util.*;
class TreeSetDemo{
    public static void main(String[] args){
        TreeSet ts = new TreeSet(new MyComparator());
        ts.add("PK");
        ts.add(new StringBuffer("Prabhas"));
        ts.add(new StringBuffer("AA"));
        ts.add("NTR");
        ts.add("MB");
        ts.add("Chiranjeevi");
        System.out.println(ts);
    }
}
class MyComparator implements Comparator{
    public int compare(Object obj1Object obj2){
        String s1 = obj1.toString();
        String s2 = obj2.toString();
        int l1 = s1.length();
        int l2 = s2.length();
        if(l1 < l2)
            return -1;
        else if(l1 > l2)
            return 1;
        else
            return s1.compareTo(s2);
    }
}

Output:
[AA, MB, PK, NTR, Prabhas, Chiranjeevi]

Comparable vs Comparator:

  • For predefined Comparable classes default natural sorting order already available, if we are not satisfied with that default natural sorting Order then we can define our own soring by using Comparator.
  • For predefined non-Comparable classes (like StringBuffer) default natural sorting order not already available, we can define our own sorting by using Comparator.
  • For our own classes like Employee, Customer, Student, ... the person who is writing the class is responsible to define default natural sorting order by implementing Comparable interface

The person who is using our class, if he is not satisfied with default natural sorting order then he can define own sorting by using Comparator.

ComparableComparator
import java.util.*;
class Employee implements Comparable<Object>{
    String empName;
    int empId;
    Employee(String empNameint empId){
        this.empName = empName;
        this.empId = empId;
    }
    public String toString(){
        return empName + "----" + empId;
    }
    public int compareTo(Object obj){
        int empId1 = this.empId;
        Employee e = (Employee)obj;
        int empId2 = e.empId;
        if(empId1 < empId2){
            return -1;
        }
        else if(empId1 > empId2){
            return 1;
        }
        else{
            return 0;
        }
    }
}
class ComparableComparatorDemo{
    public static void main(String[] args){
        Employee e1 = new Employee("Tamannah"103);
        Employee e2 = new Employee("Samantha"101);
        Employee e3 = new Employee("Anupama"104);
        Employee e4 = new Employee("KeertiSuresh"102);
        Employee e5 = new Employee("Anushka"105);
        TreeSet<Employeets = new TreeSet<Employee>();
        ts.add(e1);
        ts.add(e2);
        ts.add(e3);
        ts.add(e4);
        ts.add(e5);
        System.out.println(ts);
        TreeSet<Employeet1 = new TreeSet<Employee>(new MyComparator());
        t1.add(e1);
        t1.add(e2);
        t1.add(e3);
        t1.add(e4);
        t1.add(e5);
        System.out.println(t1);
    }
}
class MyComparator implements Comparator<Object>{
    public int compare(Object obj1Object obj2){
        Employee e1 = (Employee)obj1;
        Employee e2 = (Employee)obj2;
        String s1 = e1.empName;
        String s2 = e2.empName;
        return s1.compareTo(s2);
    }
}

Output:
[Samantha----101, KeertiSuresh----102, Tamannah----103, Anupama----104, Anushka----105]
[Anupama----104, Anushka----105, KeertiSuresh----102, Samantha----101, Tamannah----103]


Comparison of Comparable and Comparator

Comparable Comparator
It is meant for default natural sorting order It is meant for customized sorting order
Present in java.lang package Present in java.util package
It defines only one method compareTo() It defines two methods compare() and equals()
String and all Wrapper classes implements Comparable interface The only implemented classes of Comparator are Collator, RuleBasedCollator