Comparator and Comparable in Java with example
Most of the primitive datatypes have a natural order, for example, if a value is greater, less, or equal to another value. For objects, this is a bit more complicated.
If you now want to sort a list of elements of the class Person with first and last name, it is not necessarily clear how to sort. Does “Alex Foucier” come before “Bob Chignay” or vice versa?
The Comparable interface
In order to determine whether an instance is larger or smaller than another object, a class can implement the Comparable interface. Comparable only contains the compareTo() method. This accepts an object of the same type and returns an int value. The return value determines how the comparison turns out:
- The object is smaller than the transferred object: Negative int value: -1
- The object is the same size as the transferred object: Zero as a number: 0
- The object is larger than the transferred object: Positive int value: 1
[st_adsense]
If you want to sort Persons by last name, you can implement the interface Comparable or the method compareTo() as follows:
public class Person implements Comparable{ private String firstName; private String lastName; public Person(String firstName, String lastName){ this.firstName = firstName; this.lastName = lastName; } public String getFirstName() { return firstName; } public String getLastName() { return lastName; } @Override public String toString() { return "Person[firstName='" + firstName + "', lastName='" + lastName + "']"; } @Override public int compareTo(Object o) { Person other = (Person) o; return this.lastName.compareTo(other.lastName); } }
A list of Persons can now be sorted as follows:
List<Person> persons = Arrays.asList( new Person("Alex", "Sousmo"), new Person("Bob", "Carlos"), new Person("Emily", "Nohada")); Collections.sort(persons); System.out.println(persons);
Output:
[ Person{firstName='Bob', lastName='Carlos'}, Person{firstName='Emily', lastName='Nohada'}, Person{firstName='Alex', lastName='Sousmo'} ][st_adsense]
The Comparator Interface (Comparator Object)
The comparison with the compareTo() method in the Comparable Interface in the example above has a problem: how the comparison is made is fixed. If you don’t want to sort in ascending order, but in descending order or by first name, that doesn’t work.
The Comparator interface is available for these cases. It also contains a compareTo() method, but it takes two arguments of the same type. As in the case above, the return value is a negative integer if the first object is smaller than the second, a positive value if the first object is larger than the second or zero if both objects are the same size.
Now there are different ways in which the interface can be used:
Comparator class
The second possibility is to create a separate class for each sorting type. The disadvantage is that in the end many classes have to be created to cover all possibilities. The advantage is that you don’t have to create an anonymous class every time, which results in duplicate code.
public class FirstNameComparator implements Comparator<Person> { @Override public int compare(Person p1, Person p2) { return p1.getFirstName().compareTo(p2.getFirstName()); } }
The FirstNameComparator class now sorts Persons in a list by first name:
List<Person> persons = Arrays.asList( new Person("Alex", "Sousmo"), new Person("Bob", "Carlos"), new Person("Emily", "Nohada")); Collections.sort(persons, new FirstNameComparator()); System.out.println(persons);
Output:
[ Person{firstName='Alex', lastName='Sousmo'}, Person{firstName='Bob', lastName='Carlos'}, Person{firstName='Emily', lastName='Nohada'} ][st_adsense]
Anonymous class
In order not to have to always create a new class in a new Java file, a comparator object can also be created in an anonymous class:
Collections.sort(persons, new Comparator<Person>() { @Override public int compare(Person p1, Person p2) { return p1.getFirstName().compareTo(p2.getFirstName()); } });
This code has the same result as the code above, but is simple.
[st_adsense]