The comparable interface in Java ( Practical application )

First of all, let's understand why the interface exists. In a typical sorting lecture where a student is introduced to a particular sorting algorithm, the data set that will be used will most likely be an array of integers. Example sort [ 2, 6, 1, 4, 7 ] to have [ 1, 2, 4, 6, 7 ].

But the reality remains that nobody goes around sorting numbers in an array. In real software, we are most likely to be sorting a list of objects with different properties.

For example, given a list of student records with the properties name, gender, address and test score for each student which is originally arranged in alphabetical order according to student name, sort the students according to their test score in descending order. Here you cannot just iterate over the elements and then compare as you would do if it were an integer, so this is where the comparable interface comes into play.

A comparable interface in this scenario can be used to sort the students by their test scores. In this case, we will say we are using it to sort a custom object.

A comparable interface is used for sorting objects according to the natural ordering.

NOTE THE FOLLOWING

  1. Comparable interface sorts the list structures like Arrays and ArrayLists containing custom objects. This means that the comparable interface works on the individual item/object that makes up a list and not on the list. Also, it is normally used in a list where the items are not simple data type that can simply be compared but is used with data types that are objects with many fields and one of the field has to be used for the sorting.

  2. To be able to perform a sorting operation on a list, the object ( items ) in the list has to implement the Comparable interface.

  3. The Comparable interface provides only one method called compareTo that can be overridden in objects that we want to make sortable. This method allows the sorting of the items in which they are implemented. For example, if we have name and age as fields in our class object then at a time we can either sort the class objects on name or age but we cannot sort simultaneously on both name and age.

  4. The compareTo method is being used to compare the object that is being passed as an argument to the object where it is implemented. The result from this method can be interpreted as follows

    • If what is compared is the same we return 0

    • If the passed-in argument is greater we return 1

    • If the passed-in argument is smaller we return -1

    if string1 > string2, it returns positive number (1)
    if string1 < string2, it returns negative number (-1)
    if string1 == string2, it returns 0
  1. You can use the compareTo method to sort, String type objects, Wrapper class objects or User-defined. In user-defined objects, we will have to pick a particular field that will be used for the sorting.

  2. Wrapper classes of primitive data types implement comparable interface example Integer, Doubleand Character

The code below implements a custom object called Person that we wish to sort using the age field.

//class person implementing Comparable interface
class Person implements Comparable<Person> {
    private String name;
    private int age;
    //Person constructor
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    //getter methods for Person members
    public int getAge() {
        return this.age;
    }
    public String getName() {
        return this.name;
    }
    //override toString () method
    @Override
    public String toString() {
        return "";
    }
    //Override compareTo () method to compare age of two Person objects
    @Override
    public int compareTo(Person per) {
        if(this.age == per.age)
            return 0;
        else
            return this.age > per.age ? 1 : -1;
    }
}

Notice here that the compareTo method is overridden and the compareTo method is specifically design to compare numbers and will throw null pointer error if the argument passed in doesn’t have the field used for comparison. To avoid this, we can implement something like this

        @Override
    public int compareTo(Person otherPerson) {
        // Handle null checks for age field
        if (this.age == null && otherPerson.age == null) {
            return 0;  // Both ages are null, consider them equal
        } else if (this.age == null) {
            return -1; // Current age is null, consider it less than otherPerson's age
        } else if (otherPerson.age == null) {
            return 1;  // OtherPerson's age is null, consider it greater than current age
        }

        // Compare persons based on age
        return Integer.compare(this.age, otherPerson.age);
    }

Below is an implementation of insertion sort that uses the Comparable interface in the object we are sorting.

import java.util.Arrays;

public class InsertionSort {

    public static void main (String[] args){
    Student[] studentList = new Student[5];
    Student student4 = new Student("Emmanuel", 200);
    Student student1 = new Student("Unyime", 100);
    Student student2 = new Student("Udoh", 400);
    Student student3 = new Student("Daniel", 300);
    Student student5 = new Student("Jane", 100);

    studentList[0] = student1;
    studentList[1] = student2;
    studentList[2] = student3;
    studentList[3] = student4;
    studentList[4] = student5;
    System.out.println(Arrays.toString(studentList));

    SortingComponents performSort = new SortingComponents(studentList);
    performSort.sort();
    System.out.println(Arrays.toString(studentList));
    } 
}

class SortingComponents{
    Student[] studentList;
    public SortingComponents(Student[] studentList){
        this.studentList = studentList;
    }

        public void sort (){
            for(int i = 0; i < studentList.length; i++){
                int min = i;
                for (int j = i + 1; j < studentList.length; j++){
                    if(isLessThan(studentList[j], studentList[min])){
                        min = j;
                        swap(studentList, i, min);
                    }
                }
            }
        }

    public boolean isLessThan (Student studentBeingCompared, Student studentComparedWith){
        if(studentBeingCompared.compareTo(studentComparedWith) > 0){
            return false;
        }else{
            return true;
        }
    }

    public void swap(Student[] studentList, int frontIndex, int backIndex){
        Student temp = studentList[frontIndex];
        studentList[frontIndex] = studentList[backIndex];
        studentList[backIndex] = temp;
    }
}

class Student implements Comparable<Student>{
    private String name;
    private Integer level;

    public Student (String name, Integer level){
        this.name = name;
        this.level = level;
    }

    @Override
    public int compareTo(Student student){
        if(this.level > student.level){
            return 1;
        }else if (this.level < student.level){
            return -1;
        }else{
            return 0;
        }
    }
    @Override
    public String toString(){
        return "{ Name: "+ name + ", Level: " + level + " }";
    }
}

Here we have a student object that we wish to sort by levels, so we use the comparable interface. This provides a method compareTo that can be called on the student object. This method compares the student instance that is passed as an argument to the student instance on which the method is called on as shown below.

    public boolean isLessThan (Student studentBeingCompared, Student studentComparedWith){
        if(studentBeingCompared.compareTo(studentComparedWith) > 0){
            return false;
        }else{
            return true;
        }
   }

In conclusion, the comparable interface enables us to compare objects of the same type based on a particular property thus enabling sorting.

If this article was helpful, please let me know in the comment section and don't forget to follow and share. You can follow me on X.com (Twitter) and LinkedIn for more informative insight into our beloved language JAVA.

https://twitter.com/unyimeudoh22?s=09

www.linkedin.com/in/unyime-udoh-7a295626a