Package relations: + java.util + - java.lang.Comparator<T>
Parameter type:
T
- the type of objects that may be compared by this comparator
This is a functional interface.
The Comparator
is a functional interface that used to define a custom ordering for objects. This interface is useful for sorting a collection of objects that is different from their natural ordering, or when objects do not have a natural ordering using collections sort.
The Comparator
interface has a single abstract method compare()
and several default methods.
Difference between Comparable and Comparator
Comparable lets the object define its own default comparison (natural ordering). Comparator is for when you want to define a custom comparison.
compare()
The compare()
is an abstract method that compares two arguments for order.
int compare(T o1, T o2);
This method returns a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second.
Implement with anonymous nested class
You can implement the Comparator
interface and override the compare()
method using anonymous nested class. The comparator is then used by the collections sort method for sorting Person objects using custom ordering.
In this case we use the compare() method from Integer
class for defining the custom ordering.
public class Person {
int age;
String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "[" + "Name: " + name + ", Age: " + age + "]";
}
}
public static void main(String[] args) {
List<Person> people = new ArrayList<>();
people.add(new Person(12, "Tim"));
people.add(new Person(31, "John"));
people.add(new Person(23, "Jason"));
// implement using anonymous nested class
// the custom ordering is defined by Integer.compare()
// this will sort the ages in ascending order
Comparator<Person> ageComparator = new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return Integer.compare(o1.age, o2.age);
}
};
// sort with collections
Collections.sort(people, ageComparator);
System.out.println(people);
}
[[Name: Tim, Age: 12], [Name: Jason, Age: 23], [Name: John, Age: 31]]
Implement with lambda expression
Use Integer.compare()
The below is the implementation of the Comparator
interface using lambda expression.
public static void main(String[] args) {
List<Person> people = new ArrayList<>();
people.add(new Person(12, "Tim"));
people.add(new Person(31, "John"));
people.add(new Person(23, "Jason"));
// implement using lambda expression
Comparator<Person> ageComparator = (Person o1, Person o2) -> Integer.compare(o1.age, o2.age);
Collections.sort(people, ageComparator);
System.out.println(people);
}
[[Name: Tim, Age: 12], [Name: Jason, Age: 23], [Name: John, Age: 31]]
It can be further simplified as:
//...
Comparator<Person> ageComparator = (o1, o2) -> Integer.compare(o1.age, o2.age);
Collections.sort(people, ageComparator);
System.out.println(people);
Use Comparator.comparingInt()
We can also use the static method comparingInt()
that comes with the Comparator
interface to produce the same outcome.
List<Person> people = new ArrayList<>();
// ...
Comparator<Person> ageComparator = Comparator.comparingInt((Person o) -> o.age);
Collections.sort(people, ageComparator);
System.out.println(people);
The comparingInt()
method takes a ToIntFunction
, which is a functional interface that extracts an integer from an object.
public static <T> Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor) {
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> Integer.compare(keyExtractor.applyAsInt(c1), keyExtractor.applyAsInt(c2));
}
@FunctionalInterface
public interface ToIntFunction<T> { int applyAsInt(T value); }
In our case:
(Person o) -> o.age
This lambda expression is equivalent to implementing the applyAsInt()
method of the ToIntFunction
interface. The applyAsInt()
method takes an object of type T
(here, a Person
) and returns an integer (the age
).
The comparingInt()
method will create and return a Comparator
(it is also Serializable
) that compares two Person
objects (c1
and c2
) by comparing the integers extracted using the applyAsInt()
method. Internally, it uses:
Integer.compare(keyExtractor.applyAsInt(c1), keyExtractor.applyAsInt(c2));
(Learning lambda expression in Lambda Expressions and more practical examples in Stream API)
Comparator default methods
Method | Description |
---|---|
static <T> Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor) | It accepts a function that extracts an int sort key from a type T, and returns a Comparator that compares by that sort key |
static <T> Comparator<T> comparingDouble(ToDoubleFunction<? super T> keyExtractor) | It accepts a function that extracts a double sort key from a type T, and returns a Comparator that compares by that sort key |
Back to parent page: Java Standard Edition (Java SE) and Java Programming
Web_and_App_Development Programming_Languages Java Comparator Lambda_Expression Anonymous_Nested_Class