Comparable vs Comparator in Java

Comparable vs comparator - picture of apples and oranges on a see-saw

How do we compare apples with oranges? Or even apples with apples, for that matter? Do we compare based on size or colour or shape or sweetness?

We often need to compare objects in Java. Sorting, for example, is based on comparison according to some criteria. So it is important to understand the difference between Comparable and Comparator.

The Comparable interface in Java

If a class has a natural sorting order, we should implement the Comparable interface. This ensures that objects of this class can automatically be sorted when we add them to an ordered collection, such as a TreeSet or a TreeMap.

public interface Comparable {
    public int compareTo(T other);
}

The compareTo() method should return the following:

  • A negative number if the current object (this) is “less” than the other object.
  • A positive number if the current object (this) is “greater” than the other object.
  • Zero if the two objects are the same.

The meanings of “less”, “greater” and “equal” are entirely dependent on our application.

Note that equals() should be consistent with compareTo(), i.e. if equals() returns true, then compareTo() must return 0 (zero).

This sorting is referred to as the natural ordering of the class. Natural ordering is obvious for numbers and strings.

But what should we do when there isn’t an obvious (or natural) way to sort the objects? For example, how would we “naturally” sort employees? By weight, height, age, name, qualifications, salary, experience, etc.?

The Comparator interface in Java

If there isn’t an obvious way to sort our domain class, then we should not implement the Comparable interface.

Instead, we should create an object that implements the Comparator interface, and pass that object to the required ordered collection. The collection then uses that Comparator object to sort the objects in the specific way we have defined.

public interface Comparator {
    int compare(T o1, T o2);
}

The compare() method should have the same semantic behaviour as the compareTo() method.

Example code

Let’s compare (pun intended) code implementing the Comparable and the Comparator interfaces. As an example, let’s say that we want to compare Employee objects based on age.

We can implement Comparable in the Employee class:

public class Employee implements Comparable {

    // other fields
    private int age;
    
    // other methods
    @Override
    public int compareTo(Employee other) {
        return this.age - other.age;
    }
}

Adding Comparable employees to an ordered collection would be as simple as:

TreeSet ts = new TreeSet<>();

// adding lots of employee objects, sorting automatically
Employee e1 = new Employee();
ts.add(e1);

If there was no natural ordering, or we wanted to change the sorting algorithm on the fly, we would create a Comparator, and pass it to the ordered collection:

Comparator cmp = new Comparator<>() {
                                @Override
                                public int compare(Employee e1, Employee e2) {
                                    return e1.age - e2.age;
                                }
                            };
 
TreeSet ts = new TreeSet<>(cmp);

// adding lots of employee objects, sorting automatically
Employee e1 = new Employee();
ts.add(e1);

Conclusion

Which interface should you choose? Very easy! If there’s only one obvious, natural, unchanging way you want to sort objects, implement Comparable. If you want to change the sorting algorithm depending on what you need at the time, implement Comparator.

I’m always interested in your opinion, so please leave a comment. Your feedback helps me write tips that help you.

Leave a Comment

Your email address will not be published. Required fields are marked *

Code like a Java Guru!

Thank You

We're Excited!

Thank you for completing the form. We're excited that you have chosen to contact us about training. We will process the information as soon as we can, and we will do our best to contact you within 1 working day. (Please note that our offices are closed over weekends and public holidays.)

Don't Worry

Our privacy policy ensures your data is safe: Incus Data does not sell or otherwise distribute email addresses. We will not divulge your personal information to anyone unless specifically authorised by you.

If you need any further information, please contact us on tel: (27) 12-666-2020 or email info@incusdata.com

How can we help you?

Let us contact you about your training requirements. Just fill in a few details, and we’ll get right back to you.

Your Java tip is on its way!

Check that incusdata.com is an approved sender, so that your Java tips don’t land up in the spam folder.

Our privacy policy means your data is safe. You can unsubscribe from these tips at any time.