Java Comparable

Jakob Jenkov
Last update: 2020-10-04

The Java Comparable interface,java.lang.Comparable, represents an object which can be compared to other objects. For instance, numbers can be compared, strings can be compared using alphabetical comparison etc. Several of the built-in classes in Java implements the Java Comparable interface. You can also implement the Java Comparable interface yourself, to make your own classes comparable.

When a class implements the Java Comparable interface, this means that instances (objects) of that class can be compared to each other, as mentioned above. When the objects can be compared, they can be sorted using the built-in sorting functionality in Java. This sorting functionality can be used to sort collections of Java objects.

Please keep in mind that the Comparable interface is intended for comparison of objects of the same class. In other words, comparing apples to apples and oranges to oranges. It is not intended to compare apples to oranges, or strings to numbers, dates to license plates etc.

Java Comparable Definition

The Java Comparable interface is located in the java.lang package. The Java Comparable interface definition looks like this:

package java.lang;
    
public interface Comparable<T> {
 
    int compareTo(T);
    
}

As you can see, the Java Comparable interfaces only contains a single method. In the following section I will explain how the compareTo() method works.

compareTo()

The Java Comparable compareTo() method takes a single object as parameter and returns an int value. The int returned signal whether the object the compareTo() method is called on is larger than, equal to or smaller than the parameter object. More specifically:

  • A positive value (1 or larger) signals that the object the compareTo() is called on is larger than the parameter object.
  • A value of zero (0) signals that the two objects are equal.
  • A negative value (-1 or smaller) signals that the object the compareTo() methods is called on is smaller than the parameter object.

Transitive Comparison

Note, that it is a requirement when implementing the Java Comparable interface, that the implementation respects the following transitive comparison characteristics:

If A is larger than B, and B is larger than C, then A must also be larger than C.

Java Comparable Example

To better illustrate how the Java Comparable interface works, let me show you a simple example. The Java Integer class implements the Comparable interface, so you can call compareTo() Here is an example:

public class ComparableExample {

    public static void main(String[] args) {

        Integer valA = Integer.valueOf(45);
        Integer valB = Integer.valueOf(99);

        int comparisonA = valA.compareTo(valB);
        int comparisonB = valB.compareTo(valA);

        System.out.println(comparisonA);
        System.out.println(comparisonB);
    }
}

This example will print out the following lines:

-1
1

Since the value 45 is smaller than 99 - the first comparison ( valA.compareTo(valB) = 45.compareTo(99) ) results in the value -1 being returned.

In the second comparison, when 99 is compared to 45 ( valB.compareTo(valA) = 99.compareTo(45) ) the result is 1 - because 99 is larger than 45.

Implementing the Java Comparable Interface

You can implement the Java Comparable interface yourself, if you need to. Here is an example of a Spaceship class which can compare itself to other Spaceship instances:

public class Spaceship implements Comparable<Spaceship> {

    private String spaceshipClass = null;
    private String registrationNo = null;

    public Spaceship(String spaceshipClass, String registrationNo) {
        this.spaceshipClass = spaceshipClass;
        this.registrationNo = registrationNo;
    }

    @Override
    public int compareTo(Spaceship other) {
        int spaceshipClassComparison =
                this.spaceshipClass.compareTo(other.spaceshipClass);

        if(spaceshipClassComparison != 0) {
            return spaceshipClassComparison;
        }
        
        return this.registrationNo.compareTo(other.registrationNo);
    }
}    

Notice how this example implementation first compares the spaceShipClass and if they are the same, continues to compare on registrationNo. This way you can implement compareTo() to compare base on multiple factors.

Notice also how the implementation specifies that it implements Comparable<Spaceship> and not just Comparable. By specifying a type parameter when implementing the Comparable interface, the compareTo() method parameter changes from Object to whatever type you have specified. In this case the type parameter is Spaceship - and thus the parameter type becomes Spaceship too.

An implementation without a type parameter would have looked like this:

public class Spaceship implements Comparable {

    private String spaceshipClass = null;
    private String registrationNo = null;

    public Spaceship(String spaceshipClass, String registrationNo) {
        this.spaceshipClass = spaceshipClass;
        this.registrationNo = registrationNo;
    }

    @Override
    public int compareTo(Object o) {
        Spaceship other = (Spaceship) o;

        int spaceshipClassComparison =
                this.spaceshipClass.compareTo(other.spaceshipClass);

        if(spaceshipClassComparison != 0) {
            return spaceshipClassComparison;
        }

        return this.registrationNo.compareTo(other.registrationNo);
    }
}

Notice how there is no type parameter specified after the "implements Comparable" interface in the class declaration. Notice also, how the parameter type of the compareTo() object is no longer Spaceship, but Object. Finally, also notice how it is now necessary to cast the parameter of the compareTo() method to Spaceship explicitly.

Notice too, that the compareTo() method should throw a NullPointerException if the parameter object is null. This means you do not have to do a null check before comparing the objects.

Similarly, the compareTo() method should throw a ClassCastException if the input parameter is not of the same class as the class of the object compareTo() is called on. Thus, no explicit type check is necessary. You can just cast to the desired class (as in the example above). If the classes do not match, the Java VM will throw a ClassCastException.

Jakob Jenkov

Featured Videos

Java Generics

Java ForkJoinPool

P2P Networks Introduction



















Close TOC
All Tutorial Trails
All Trails
Table of contents (TOC) for this tutorial trail
Trail TOC
Table of contents (TOC) for this tutorial
Page TOC
Previous tutorial in this tutorial trail
Previous
Next tutorial in this tutorial trail
Next