Java Comparable and Comparator

Comparable & Comparators

When it comes to programming in virtually any language, a common requirement is to sort and manipulate data. For example we might have a list of grades obtained from students in a class room.

Often times you will want to rank these grades from the highest score (lets say 100%) to the lowest score (0%) in order to get an impression of how students are performing. You could manually rearrange all the student grades yourself or you could have a program that sorts these values for you.

In Java we have the following operators used to compare number values.

• Greater than: > (5 > 4)
• Less than: < (1 < 3)
• Greater than or equal to: >= (5 >= 5)
• Less than or equal to: <= (4 <= 4)
• Equal to: == (2 == )

You can also sort values by lexicographical order, otherwise known as alphabetic order. In this case a < b when referring to which letter comes first in the alphabet.

There can also be sorting by the length of a string in Java, such as “small” > “big”, in which the word small has fewer letters than big. There are endless ways of comparing strings, numbers, and all other data types. These are fundamental constructs of mathematics and programming in general.

In the Java programming language, these comparisons are called conditional operators. They check the condition of an expression such as 5 > 4 and if the result is true, it will return a boolean value of true or false. For instance, 4 > 5 would result in false. This is pretty straightforward and easy to understand, but what happens when you start moving towards object oriented programming?

Object Oriented Programming

In Java we define classes which combine and encapsulate similar data together.

Examples of classes include

• Student class – This may contain values like a student name, student ID, a list of grades, and any other data pertaining to the student.
• Car class – Can contain data such as make, model, year, or other features of a vehicle.
• Animal class – Again this can have generic traits of all animals such as type of animal, weight of the animal, color, or anything else used to describe the animal.

The list can go on forever, you are free to define classes of anything you can think of!

The problem that we run into is how do we sort, arrange, or otherwise categorize all these different classes?

Java programs consist of objects.

Once we have a class defined such as student, we can begin creating different instances of those students by instantiating the class. This is where we actually create an individual object from that class.

Continuing with our student example, we will need an instance (one object) of a student class for every single student in the class. This means we would have 30 student objects for a class of 30 students.

Here is an example of what a student class might look like:

package com.jasont.compare;

public class Student {
private String name;
private int id;

Student(String name, int id, double grade) {
this.name = name;
this.id = id;
}
//Setter and getter methods below...
}

This is a very basic student class with a String for their name, an integer for their id, and an array of doubles for their grade. I have excluded the setter and getter methods for brevity.

Now lets examine how to create multiple student objects within our main driver.

package com.jasont.compare;

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

public class ClassRoom {
public static void main(String[] args) {
List<Student> classRoom = new ArrayList<>();

classRoom.add(new Student("Billy", 1, 94.30));
classRoom.add(new Student("Susy", 3, 85.44));
classRoom.add(new Student("Trevor", 2, 89.00));
classRoom.add(new Student("Alice", 5, 95.20));
classRoom.add(new Student("Thomas", 4, 82.37));

System.out.println(classRoom.toString().replaceAll("[,\\[\\]]","").replace(" N", "N"));
}
}

In our main driver program we declare and instantiate a new array list which holds our student objects. Then five students are added to the list, by creating a new student object constructor for each element of the array list. Finally the student list is displayed to the console.

Internally array lists have a toString() method that will automatically format the data inside of the list as a string for output. The replace and replaceAll methods are just added to remove commas, square brackets, and unneeded spaces which are added automatically by the array list. This will make the output look cleaner.

Now say you are a teacher and have a huge list of students and would like to list the students in order of their grades.

How would you go about sorting these student objects?

The most commons way to sort a collection is through the Collections.sort() method, which would work great on wrapper data types or strings, but how will the sort method figure out how to sort an object containing multiple types of data?

The answer is… sort() doesn’t know, but we have a solution!

We can implement the Comparable interface.

Implementing Comparable

Implementing this interface directly within your class allows you to do the following.

1. Call Collections.sort() and Collections.binarySearch() upon your list of custom objects.
2. Use Arrays.sort() and Arrays.binarySearch() on an array of custom objects.
3. Adding objects as you key value inside of a TreeMap, which will automatically order your elements on insertion.
4. Add objects inside of a TreeSet, which will sort your elements automatically.

The comparable interface is useful when we want meaningful way to have our objects ordered. There are only two changes you must make to your student class.

1. Append implements Comparable<Student> to the end of your student class.
2. Override the compareTo method contained inside Comparable.

Here is an example of comparable being implemented within the student class.

package com.jasont.compare;

public class Student implements Comparable {
private String name;
private int id;