TreeSet Custom Comparator
Fast recall
Quick revision
Core answer
new TreeSet<>(Comparator.comparingInt(String::length)). The comparator is fixed at construction — you can't change it later. Watch the trap: if compare() returns 0 for two distinct objects, TreeSet treats them as duplicates and drops the second.Practical knowledge of TreeSet construction and Comparator usage for custom ordering
Attempting to set or change the Comparator after TreeSet creation, which is impossible
Explain that if the Comparator returns zero for two different objects, TreeSet treats them as duplicates and rejects the second one, even if they're not equal
Interview-ready guide
Interview answer
You create a TreeSet with custom ordering by passing a Comparator to its constructor.
comparingInt using the length method reference. The important thing is that the comparator is fixed when you create the TreeSet. There's no way to change it later, so if you need different sorting, you build a new TreeSet with a new comparator and add the elements again.
One thing that trips up freshers is how TreeSet detects duplicates. It uses the comparator, not the equals method. So if your comparator returns zero when comparing two objects, TreeSet thinks they're the same and rejects the second one, even if they're actually different objects.
For instance, if you sort orders by priority only, two orders with the same priority look identical to the TreeSet, and it'll only keep one of them. That's why you usually want a tiebreaker in your comparator, like sorting by priority first, then by id. That way every distinct object gets a unique position.
The key is understanding that the comparator controls both the ordering and the duplicate detection in a TreeSet.
TreeSet Custom Comparator
Direct Answer
Pass a Comparator to the constructor: new TreeSet<>(Comparator.comparingInt(String::length)). The comparator is fixed at construction — you can't change it later. Watch the trap: if compare() returns 0 for two distinct objects, TreeSet treats them as duplicates and drops the second.
Code Example
The first set uses a safe multi-field comparator. The second shows the duplicate trap when the comparator looks at only one field.
import java.util.*;
public class CustomSortedOrders {
record Order(Long id, String item, int priority) {}
public static void main(String[] args) {
// Sort by priority (high to low), then by id as a tiebreaker
var byPriority = new TreeSet<Order>(
Comparator.comparingInt(Order::priority).reversed()
.thenComparingLong(Order::id));
byPriority.add(new Order(101L, "Laptop", 1));
byPriority.add(new Order(102L, "Mouse", 3));
byPriority.add(new Order(103L, "Keyboard", 3)); // kept: id breaks the tie
System.out.println("Safe size: " + byPriority.size()); // 3
// DANGER: comparator on priority alone treats equals as duplicates
var byPriorityOnly = new TreeSet<Order>(Comparator.comparingInt(Order::priority));
byPriorityOnly.add(new Order(101L, "Laptop", 1));
byPriorityOnly.add(new Order(102L, "Mouse", 1)); // dropped: same priority
System.out.println("Trap size: " + byPriorityOnly.size()); // 1, not 2
}
}
The thenComparingLong(Order::id) tiebreaker is what saves the first set from collapsing two same-priority orders into one.
Common Mistakes & Pitfalls
- Comparator inconsistent with equals: a comparator on one field (like priority) returns 0 for objects that differ elsewhere, so
TreeSetdrops the second as a duplicate. It loses data silently — add a tiebreaker field. - Trying to change the comparator after creation: there is no
setComparator. To re-sort, build a newTreeSetwith the new comparator and copy the elements over. - Adding null with a comparator: a
TreeSetaccepts null only if its comparator explicitly supports it; natural ordering rejects null.
Check your understanding
Answer these without looking back at the article.
- What happens when two elements have the same Comparator value?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.