Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Java

Comparator and Comparable Objects

4.86/5 (5 votes)
29 Dec 2013CPOL3 min read 27.2K   125  
Comparator and Comparable objects tutorial

Introduction

There is a lot of confusion among beginners about Comparators and Comparable. The main reason is the lack of understanding about what they are and the difference between them.

Background

CompareTo – Method that compares between the current element that initiates the method and another object that passed in the method. The method returns a positive number if the current element is bigger than the passed element, negative if it's smaller and 0 if they are equal.

Natural ordering – The most suitable parameter to be used to compare at the current class. For example, Employee often compared by their "Performances".

Understanding Definitions

Comparable

Object that can be compared with other objects by their narutal ordering.

Implementing Comparable means "I can compare myself with another object." This is typically useful when there's a single natural default comparison. © Jon Skeet.

Example: If I have an IdCard class, then the natural ordering for this scenario is by Id number.

Comparator

Independent specific class that is targeted for comparing two objects by specific field.
Comparators allow us to add more ways for comparing objects.

Implementing Comparator means "I can compare two other objects." This is typically useful when there are multiple ways of comparing two instances of a type. © Jon Skeet.

Example: We can compare 2 people by properties like Age, Height, etc.

Comparable

Person.java

Java
 public class Person implements Comparable<Object> {
    
    public int id;
    public String name;
    public int age;
    public int height;

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

    @Override
    public int compareTo(Object o) {
        return this.id - ((Person)o).id;
    }
    
    @Override
    public String toString() {
        return String.format("[Name: %s/Age: %d/Height: %d]", name, age, height);
    }
} 

To illustrate the Comparable interface, I choose to create a simple Person class. I gave this class a constructor with the following fields: id, name, age and height. I've used the Comparable<Object> interface and implemented its compareTo method. Because Person object in my program is compared by id, I've implemented the compareTo to be subjected to the object id member. This can easily be changed to suit your own Class. We can now compare the person objects with other person objects, a comparison will look like this:

Java
// Comparable
System.out.println("Is Bar id bigger than Sam ? " + pBar.compareTo(pSam)); 

Output

Java
System.out.println("Is Bar id bigger than Sam ? " + pBar.compareTo(pSam));

Another Example: A Man's Wallet

We know that wallet will usually be compared by the amount of money it's containing. So a suitable Wallet class will look like this:

Java
 public class Wallet implements Comparable<Object> {
    
    public int money = 0;
    public String name;
    
    public Wallet(String name, int money) {
        this.name = name;
        this.money = money;
    }
    
    @Override
    public int compareTo(Object o) {
        return this.money - ((Wallet)o).money;
    }
} 

Comparators

Comparators are independent classes which implement "Comparator" interface.

Comparators main usages are for sorting, each comparator will implement inside compareTo their own sort logic. And later, the comparator will be passed through a sorting algorithm that will be used the passed comparator sorting logic.

For example: HeightComparator will compare the height field from two objects.

HeightComparator.java

Java
 import java.util.Comparator;

public class HeightComparator implements Comparator<Object> {

    @Override
    public int compare(Object o1, Object o2) {
        int p1 = ((Person)o1).height;
        int p2 = ((Person)o2).height;
        return p1 - p2;
    }
} 

This comparator is casting both received objects into Person objects and returning a positive number when the first object is bigger than the second, else negative number when the second object is bigger than the first one, otherwise it is returning zero because both of them are equal.

Comparator has another usage. We can use it without sorting the whole collection, by creating the targeted comparator and then passing it the objects we want to compare.

Exploring the Examples

MainClass.java

Java
// Declaring Person objects.
ArrayList<Person> peoples = new ArrayList<Person>();
Person pOrel = new Person(1, "Orel", 27, 186);
Person pBar = new Person(2, "Bar", 28, 165);
Person pSam = new Person(3, "Sam", 25, 170);
peoples.add(pOrel);
peoples.add(pBar);
peoples.add(pSam); 

I created an Person ArrayList to hold our collection. I've created 3 Person instances and added them into our collection.


Java
// Comparable
System.out.println("Is Bar id bigger than Sam ? " + pBar.compareTo(pSam)); 

I've tested the Person compare method by comparing to see if pBar is bigger than pSam, as we know this will use Person compareTo method to see if pBar id number is bigger than pSam id number (false, pSam id is bigger).

Output

Java
Is Bar id bigger than Sam ? -1

Java
// Comparators 2nd usage.
System.out.println("Does Orel taller than Sam ? " + 
                    new HeightComparator().compare(pOrel, pSam)); 

I've used specific comparator in order to discover if pOrel is taller than pSam.

Output

Java
Does Orel taller than Sam ? 16 

Java
// Comparators 1st usage.
// Passing Collections sort methods our collection and the 
// specified Comparator we want to use in order to sort the collection.
Collections.sort(peoples, new AgeComparator());
System.out.println("Compare by Age");
MyLibrary.printObjects(peoples); 

I'm passing our sorting algorithm peoples collection and AgeComparator in order to sort our collection by the logic inside the compare method inside AgeComparator. Then using a normal static method to print the result.

Output

Java
Compare by Age
[Name: Sam/Age: 25/Height: 170] [Name: Orel/Age: 27/Height: 186] 
[Name: Bar/Age: 28/Height: 165]  

Conclusion

Using Comparable and Comparators can easily simplify your code when tasks for sorting are needed. It will make your code more generic, readable and clean.

History

  • 28th December, 2013: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)