Intermediate · The collections framework · topic 34 of 60 · 25 min
Sorting with Comparable and Comparator
Explanation
Natural order with Comparable
Strings sort alphabetically and numbers numerically because those classes implement Comparable. compareTo(other) returns a negative number if this comes first, zero if equal, and a positive number if this comes after.
public record Employee(String name, String dept, int salary) implements Comparable<Employee> {
@Override
public int compareTo(Employee other) {
return this.name.compareTo(other.name); // natural order: by name
}
}
List<Employee> staff = new ArrayList<>(List.of(
new Employee("Ravi", "IT", 65000),
new Employee("Asha", "HR", 52000),
new Employee("Meena", "IT", 78000)));
Collections.sort(staff); // uses compareTo: Asha, Meena, RaviOther orders with Comparator
A class has only one natural order, but reports need many: by salary, by department then name, highest first. A Comparator is a separate object (often a lambda) that compares two objects. Comparator factory methods make this readable.
staff.sort(Comparator.comparingInt(Employee::salary)); // lowest salary first
staff.sort(Comparator.comparingInt(Employee::salary).reversed()); // highest first
staff.sort(Comparator.comparing(Employee::dept)
.thenComparing(Employee::name)); // by dept, then name
staff.sort((a, b) -> Integer.compare(b.salary(), a.salary())); // a lambda by hand
staff.sort(Comparator.comparing(Employee::name, String.CASE_INSENSITIVE_ORDER));Sorting arrays and other collections
String[] cities = {"pune", "Agra", "delhi"};
Arrays.sort(cities, String.CASE_INSENSITIVE_ORDER); // [Agra, delhi, pune]
TreeSet<Employee> bySalary = new TreeSet<>(Comparator.comparingInt(Employee::salary));
PriorityQueue<Employee> queue = new PriorityQueue<>(Comparator.comparingInt(Employee::salary).reversed());Handling nulls and keys that are missing
If some values can be null (for example an employee with no department yet), comparing them throws NullPointerException. Comparator.nullsFirst(...) and nullsLast(...) wrap another comparator and place nulls at the start or the end instead.
staff.sort(Comparator.comparing(Employee::dept, Comparator.nullsLast(Comparator.naturalOrder())));
// employees without a department are listed at the end instead of crashing the sortStable sorting
Java's object sort (List.sort, Collections.sort) is stable: elements that compare as equal keep their original relative order. That is why sorting by name and then sorting by department gives department groups with names still in order, although thenComparing is clearer.
Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
Sorting with Comparable and Comparator · 1/6
In this lesson you will sort objects in any order you need.
Prefer a video by a teacher? Find free videos on “java comparable vs comparator comparing thenComparing reversed” on YouTube ↗
In real life: Ranking delivery partners
A delivery platform ranks partners for incentives: highest rating first, then most deliveries, then name for a stable tie-break. One comparator chain expresses the whole policy.
record Partner(String name, double rating, int deliveries) {}
Comparator<Partner> ranking = Comparator.comparingDouble(Partner::rating).reversed()
.thenComparing(Comparator.comparingInt(Partner::deliveries).reversed())
.thenComparing(Partner::name);
partners.sort(ranking);Practice (0/3 done)
List<String> l = new ArrayList<>(List.of("bb", "a", "ccc")); l.sort(Comparator.comparing(String::length).reversed()); What is l?
The same comparator chain in JavaScript, which runs here: write rankStaff(staff) that returns a NEW array sorted by dept A–Z, then by salary highest first, then by name A–Z. Items are { name, dept, salary }.
Create a record Product(String name, double price, int rating). Make it Comparable by name. Then sort a list of products (a) by natural order, (b) by price lowest first, (c) by rating highest first then price lowest first, printing the list each time.
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- Queues, stacks and priority queuesThe collections framework · same module
- Sorting in real code: keys, comparators, counting sortData Structures and Algorithms (DSA) for interviews · Sorting and searching
- Sorting with keyPython Programming · Working with data
- Method referencesLambdas, streams and files
- Simple sorts: bubble, selection and insertionData Structures and Algorithms (DSA) for interviews · Sorting and searching
- Generics: type parameters and constraintsGo Programming (backend and cloud) · Packages, testing and generics
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
a.compareTo(b) returns a negative number. What does it mean?
Answer: a comes before b
Negative means a sorts first.
How many natural orders can a class have?
Answer: One (Comparable)
Other orders use Comparators.
Why avoid (a, b) -> a.x - b.x?
Answer: Subtraction can overflow and give the wrong sign
Use Integer.compare.
Is List.sort stable?
Answer: Yes, equal elements keep their order
Java's object sort is stable.
Which key sorts (name, marks) tuples by marks high to low, then name A to Z?Related
Answer: lambda s: (-s[1], s[0])
The tuple compares marks first (negated for high to low), then the name.
What does it mean that Python sorting is stable?Related
Answer: Items with equal keys keep their original order
A stable sort keeps the earlier of two equal items first.
From Sorting with key
Which Set keeps insertion order?Related
Answer: LinkedHashSet
LinkedHashSet remembers insertion order.
A PriorityQueue<Integer> created with no comparator gives…Related
Answer: The smallest first
The default is a min-heap by natural order.
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- 1 more topic in “The collections framework” before its exam: Queues, stacks and priority queues.
- Module 7 exam: The collections framework · 12 questions · 25 min, without help. 5 topics of this module still to finish first.
- Then the next module, Lambdas, streams and files. 60 topics left in the course before the final exam.