Java Comparable
Jakob Jenkov |
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.
Tweet | |
Jakob Jenkov |