Difference between Comparable and Comparator in Java with Examples

Munish Chandel | August 02, 2018 at 08:32 AM | 80 views


Both comprabale and comparator are interfaces from Java Collections Framework that allow sorting of collections. But both of these interfaces are meant for different purpose.
Comparable Comparator

Imposes a total ordering on the objects of each class that implements it. This ordering is referred to as class’s natural ordering, and the class’s compareTo method is referred to as its natural comparison method.

It is a comparison function, which imposes a total ordering on some collection of objects.

Comparable provides only single sorting sequence (based on single or multiple fields)

N number of comparators can be created for different sorting sequences

Comparable affects the original class

Unlike Comparable, Comparator is external to original class that we are comparing.

Comparable provides compareTo(T other) method for defining natural ordering of class

Comparator provides compare(T o1, T o2) to sort elements

It is part of java.lang package

It is part of java.util package

Collection.sort(List), SortedMap and SortedSet can use this

This function can be passed to Collections.sort(List, Comparator), SortedSet and SortedMap to allow precise control of sorting order.

It is strongly recommended that natural ordering be consistent with equals, else sorted set and sorted map will behave strangely. Virtually all Java classes that implement comparable have natural orderings that are consistent with equals

No such requirements

Example Code

Lets take a concrete example of Comparable and Comparator

Person class with Natural ordering based on name
class Person implements Comparable<Person>{
    int age;
    String name;
    String email;

    @Override
    public int compareTo(Person o) {
        return name.compareTo(o.getName());
    }
}

Now we can sort a collection of persons based on its natural ordering using Collections.sort method.

Sorting in Natural Order
List<Person> students = Arrays.asList(
        new Person(20,"Bob", "bob@mail.com"),
        new Person(19, "Jane", "Jane@mail.com"),
        new Person(21,"Foo", "foo@mail.com")
);
Collections.sort(students);

This program will always sort persons based on their name i.e. Bob → Foo and thenJane.

Lets define two comparators now, one for name based comparison and another on basis of age.

class NameComparator implements Comparator<Person> {

    @Override
    public int compare(Person o1, Person o2) {
        return o1.name.compareTo(o2.name);
    }
}

class AgeComparator implements Comparator<Person> {

    @Override
    public int compare(Person o1, Person o2) {
        return ((Integer)o1.age).compareTo(o2.age);
    }
}

Now we can specify one of the above defined sorting function to choose sorting on demand:

Soritng based on Age
List<Person> students = Arrays.asList(
        new Person(20,"Bob"),
        new Person(19, "Jane"),
        new Person(21,"Foo")
);
Collections.sort(students, new AgeComparator());

Eay enough?

Chaining of comparison operations in Java 8

Java 8’s lambda expressions brings syntax improvements to sorting capabilities of Java Collections Framework. We can even chain multiple sorting operations using chaining of operations, as shown in below code:

Comparing by name and then age (if name is same)
List<Person> students = Arrays.asList(
        new Person(20,"Foo"),
        new Person(19, "Jane"),
        new Person(21,"Foo")
);
Collections.sort(students);
students.stream()
        .sorted(Comparator
                .comparing(Person::getName)
                .thenComparing(Person::getAge)
        ).forEach(System.out::println);

Even reverse sort is easy enough:

Soritng by Name and then Age in reverse order
students.stream()
        .sorted(Comparator
                .comparing(Person::getName)
                .thenComparing(Person::getAge)
                .reversed() (1)
        ).forEach(System.out::println);
1 Sorting Age in reverse direction. reversed() Returns a comparator that imposes the reverse ordering of this comparator.

Case insensitive ordering

For certain fields like email, case does not matter. Its easy to achieve this using Java 8:

Case insensitive ordering for email
students.stream()
        .sorted(Comparator
                .comparing(Person::getName)
                .thenComparing(Person::getAge)
                .thenComparing(Person::getEmail, Comparator.nullsLast(String.CASE_INSENSITIVE_ORDER))
        ).forEach(System.out::println); (1)
1 null values are pushed to last

Buy DRM Free PDF for Complete Collection of Interview Questions
Generic placeholder image
ebook PDF - Cracking Java Interviews v3.4 by Munish Chandel

240 real Java interview questions on core Java, concurrency, algorithms, design & data structures, spring, hibernate for Investment Bank, Healthcare IT, product and service based companies, Author : Munish Chandel, Price: 250, Type: PDF

Free Email Updates
Subscribe to Blog via Email

Enter your email address to subscribe to this blog and receive notifications of new posts by email.


Similar Articles:
  1. Java 8 – HijrahDate, How to calculate the Ramadan date
  2. How to find if the Linked List contains any Cycle/Loop
  3. How will you calculate factorial of a large number in Java
  4. Generate Random Numbers in a range using Java 8
  5. What is difference between JDK JRE and JVM
  6. Difference between Comparable and Comparator in Java with Examples

This website uses cookies to ensure you get the best experience on our website. more info