Java Comparable & Comparator
In this page:
class ClassName implements Comparable<ClassName> {
public int compareTo(ClassName other) {
return Integer.compare(this.field, other.field);
}
}
Comparator<ClassName> comparator = Comparator.comparing(ClassName::getField);
Natural Sorting with Comparable
You can define a default, natural sort order for your own custom classes by implementing the Comparable interface and overriding its compareTo method. Collections like TreeSet and TreeMap will automatically use this natural ordering unless you explicitly supply something else.
Example: Natural Sorting with Comparable
// Import java.util.* so it can be used by its short name
import java.util.*;
// Define the class Main
public class Main {
// Define the class Person
static class Person implements Comparable<Person> {
String name; int age;
Person(String name, int age) { this.name = name; this.age = age; }
public int compareTo(Person other) { return Integer.compare(age, other.age); }
public String toString() { return name + "(" + age + ")"; }
}
// Program entry point: the JVM starts running here
public static void main(String[] args) {
// Create a new ArrayList object and store it in people
List<Person> people = new ArrayList<>(List.of(new Person("Bo", 30), new Person("Al", 20)));
Collections.sort(people);
// Print a line to the console
System.out.println(people);
}
}
Login to try C/C++/Java/PHP code in the editor
Custom Sorting with Comparator
If you want to sort the same objects in several different ways without touching their class definition, you can define a separate class implementing the Comparator interface for each ordering you need. This decouples the sorting logic entirely from the object being sorted.
Example: Custom Sorting with Comparator
// Import java.util.* so it can be used by its short name
import java.util.*;
// Define the class Main
public class Main {
// Define the class ByName
static class ByName implements Comparator<String> {
public int compare(String a, String b) { return a.compareTo(b); }
}
// Program entry point: the JVM starts running here
public static void main(String[] args) {
// Create a new ArrayList object and store it in names
List<String> names = new ArrayList<>(List.of("Zoe", "Amy", "Max"));
names.sort(new ByName());
// Print a line to the console
System.out.println(names);
}
}
Login to try C/C++/Java/PHP code in the editor
Comparator Lambda Syntax
You can write ad-hoc comparators quickly using lambda expressions instead of declaring a whole named class purely for one comparison. This is the most common way comparators are written in modern Java code, especially for one-off sorts.
Example: Comparator Lambda Syntax
// Import java.util.* so it can be used by its short name
import java.util.*;
// Define the class Main
public class Main {
// Program entry point: the JVM starts running here
public static void main(String[] args) {
// Create a new ArrayList object and store it in names
List<String> names = new ArrayList<>(List.of("Zoe", "Amy", "Max"));
names.sort((a, b) -> a.compareTo(b));
// Print a line to the console
System.out.println(names);
}
}
Login to try C/C++/Java/PHP code in the editor
Chaining Comparators
You can chain several comparators together using the thenComparing() method to define fallback sorting rules, so that when two elements tie on the primary comparison, the next comparator in the chain breaks the tie, and so on down the chain.
Example: Chaining Comparators
// Import java.util.* so it can be used by its short name
import java.util.*;
// Define the class Main
public class Main {
// Define the record Person (an immutable data carrier)
record Person(String name, int age) {}
// Program entry point: the JVM starts running here
public static void main(String[] args) {
// Create a new ArrayList object and store it in people
List<Person> people = new ArrayList<>(List.of(new Person("Amy", 30), new Person("Amy", 20)));
people.sort(Comparator.comparing(Person::name).thenComparing(Person::age));
// Print a line to the console
System.out.println(people);
}
}
Login to try C/C++/Java/PHP code in the editor
Null-Safe Comparators
Sorting a collection that contains null elements with a custom comparator can throw a NullPointerException the moment the comparator tries to compare against one. You can guard against this by wrapping your comparator with Comparator.nullsFirst() or nullsLast(), which push nulls to whichever end of the ordering you choose.
Example: Null-Safe Comparators
// Import java.util.* so it can be used by its short name
import java.util.*;
// Define the class Main
public class Main {
// Program entry point: the JVM starts running here
public static void main(String[] args) {
// Create a new ArrayList object and store it in names
List<String> names = new ArrayList<>(Arrays.asList("Zoe", null, "Amy"));
names.sort(Comparator.nullsFirst(Comparator.naturalOrder()));
// Print a line to the console
System.out.println(names);
}
}
Login to try C/C++/Java/PHP code in the editor
- Calling
Collections.sort(list)on a class that does not implementComparable, which does not compile; implementComparableor pass a Comparator. - Writing a comparator as
a.age - b.age, which can overflow for large values; useInteger.compare(a.age, b.age). - Sorting a list that contains
nullvalues with a plain comparator, which throws aNullPointerException; wrap it withComparator.nullsFirst.
Chapter Quiz — Complete all 4 topics to unlock
0/4 topics done
Complete these topics first: