Guide to Comparable Interface

As we know that comparing primitive values like int, char, float is very easy and can be done with comparison operators like <, >, == etc.
But comparing objects is a little different. For example, how would you compare two Employees? how would you compare two Students?
You need to explicitly define how the objects of user-defined classes should be compared. For this purpose, Java provides two interfaces called Comparable and Comparator.

In this guide, we will the Comparable Interface in detail with examples.

1. What Will We Learn?

  • Overview of Comparable Interface
  • Sort User-Defined Objects in Ascending Order.
  • Sort User-Defined Objects in Descending Order
  • Sort String and Wrapper Classes
  • More Examples

2. Overview of Comparable Interface

By default, a user-defined class is not comparable. That is, its objects can’t be compared. To make an object comparable, the class must implement the Comparable interface.
The Comparable interface has a single method called compareTo() that you need to implement in order to define how an object compares with the supplied object -
public interface Comparable<T> {
     public int compareTo(T o);
}
When you define the compareTo() method in your classes, you need to make sure that the return value of this method is -
  • negative, if this object is less than the supplied object.
  • zero, if this object is equal to the supplied object.
  • positive, if this object is greater than the supplied object. Many predefined Java classes like String, Date, LocalDate, LocalDateTime etc implement the Comparable interface to define the ordering of their instances.
Comparable Interface provides default ordering for the objects of a class. This default ordering is also called the natural ordering of the objects. 
For Example, If the List consists of String elements, it will be sorted into alphabetical order. If it consists of Date elements, it will be sorted into chronological order. How does this happen? String and Date both implement the Comparable interface. 
Comparable implementations provide a natural ordering for a class, which allows objects of that class to be sorted automatically.
Let's see how to implement the Comparable interface in a user-defined class and define the compareTo() method to make the objects of that class comparable.

3. Sort User-Defined Objects in Ascending Order

This is example demonstrate that we create a list of person objects and we compare each person's age by using compateTo() method of Comparable Interface.
In short, we are sorting persons by age in ascending order.
public class Person implements Comparable<Person> {

 private int id;

 private String name;

 private int age;

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

 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;
 }

 @Override
 public String toString() {
  return this.name;
 }

 @Override
 public int compareTo(Person otherPerson) {
  return (this.getAge() - otherPerson.getAge());
 }
}
import java.util.ArrayList;

import java.util.Collections;
import java.util.List;

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

  sortUserDefinedObjectsInAsc();
 }

 private static void sortUserDefinedObjectsInAsc() {
  List<Person> persons = new ArrayList<Person>();
  Person person1 = new Person(59, "John", 40);
  Person person12 = new Person(67, "Roger", 25);
  Person person13 = new Person(45, "Steven", 30);
  persons.add(person1);
  persons.add(person12);
  persons.add(person13);

  System.out.println("Before Sorting : " + persons);
  Collections.sort(persons);
  System.out.println("After Sorting : " + persons);
 }
}
Output:
Before Sorting : [John, Roger, Steven]
After Sorting : [Roger, Steven, John]

4. Sort User-Defined Objects in Descending Order

Java provides in build utility method sort() and Collections.reverseOrder() to sort the objects in descending order.

Collections.reverseOrder()

Returns a comparator that imposes the reverse of the natural ordering on a collection of objects that implement the Comparable interface.
Collections.sort(persons, Collections.reverseOrder());
This example demonstrates that we are sorting person objects by age in descending order.
public class PersonSorterInDESC {

 public static void main(String[] args) {
  sortUserDefinedObjectsinDesc();
 }
 
 private static void sortUserDefinedObjectsinDesc(){
  List<Person> persons = new ArrayList<Person>();
  Person person1 = new Person(59, "John", 40);
  Person person12 = new Person(67, "Roger", 25);
  Person person13 = new Person(45, "Steven", 30);
  persons.add(person1);
  persons.add(person12);
  persons.add(person13);

  System.out.println("Before Sorting : " + persons);
  Collections.sort(persons, Collections.reverseOrder());
  
  System.out.println(" Sort in decending order : " + persons);

 }
}
Output:
Before Sorting : [John, Roger, Steven]
Sort in decending order : [John, Steven, Roger]

5. Sort String and Wrapper Classes

Let's see the sorting of String and Wrapper classes because these classes internally implement the Comparable interface.

5.1 Sort String objects

List<String> names = new ArrayList<>();
names.add("ABC");
names.add("ACB");
names.add("PQR");
names.add("CDQ");

System.out.println("Before Sorting : " + names);
Collections.sort(names);
System.out.println("After Sorting : " + names);
Output
Before Sorting : [ABC, ACB, PQR, CDQ]
After Sorting : [ABC, ACB, CDQ, PQR]

5.2 Sort Wrapper Class objects

List<Integer> names = new ArrayList<>();
names.add(100);
names.add(20);
names.add(10);
names.add(50);

System.out.println("Before Sorting : " + names);
Collections.sort(names);
System.out.println("After Sorting : " + names);
Output:
Before Sorting : [100, 20, 10, 50]
After Sorting : [10, 20, 50, 100]

6. More Examples

The following class representing a person's name implements Comparable
public class Name implements Comparable<Name> {
    private final String firstName, lastName;

    public Name(String firstName, String lastName) {
        if (firstName == null || lastName == null)
            throw new NullPointerException();
        this.firstName = firstName;
        this.lastName = lastName;
    }

    public String firstName() { return firstName; }
    public String lastName()  { return lastName;  }

    public boolean equals(Object o) {
        if (!(o instanceof Name))
            return false;
        Name n = (Name) o;
        return n.firstName.equals(firstName) && n.lastName.equals(lastName);
    }

    public int hashCode() {
        return 31*firstName.hashCode() + lastName.hashCode();
    }

    public String toString() {
 return firstName + " " + lastName;
    }

    public int compareTo(Name n) {
        int lastCmp = lastName.compareTo(n.lastName);
        return (lastCmp != 0 ? lastCmp : firstName.compareTo(n.firstName));
    }
}
Here's a program that builds a list of names and sorts them.
public class NameSort {
    public static void main(String[] args) {
        Name nameArray[] = {
            new Name("John", "Smith"),
            new Name("Karl", "Ng"),
            new Name("Jeff", "Smith"),
            new Name("Tom", "Rich")
        };

        List<Name> names = Arrays.asList(nameArray);
        Collections.sort(names);
        System.out.println(names);
    }
}
If you run this program, here's what it prints.
[Karl Ng, Tom Rich, Jeff Smith, John Smith]



Comments

Post a Comment