TreeSet uses comparator equality to decide whether a candidate is already present, even when the objects have different identifiers.
Java TreeSet comparator collisions: compare zero means one slot
A lossy comparator drops work
Two review jobs share priority one but have different receipt IDs. A TreeSet ordered only by priority rejects the second job. A comparator with receipt ID as a tie-breaker retains both. The program prints sizes, avoiding any dependence on a representation order for the rejected set.
This is a data-loss boundary. If two distinct business objects may compare as zero, a sorted set is not a safe queue until the comparator defines their identity. PriorityQueue tie order has a different contract: a priority queue can hold equivalent-ranked jobs, but their removal order is unspecified.
Use an ordering that matches the key model
A comparator must be transitive. Subtraction is a poor shortcut when integer overflow is possible. If equality and ordering describe different concepts, use a list or a map keyed by explicit ID instead of forcing both into one TreeSet.
Working program
import java.util.Comparator;
import java.util.TreeSet;
public class ReviewJobSet {
static final class Job {
final String receiptId; final int priority;
Job(String receiptId, int priority) { this.receiptId = receiptId; this.priority = priority; }
}
public static void main(String[] args) {
Job east = new Job("R-41", 1);
Job west = new Job("R-42", 1);
TreeSet<Job> lossy = new TreeSet<>(Comparator.comparingInt(job -> job.priority));
lossy.add(east);
System.out.println("second accepted=" + lossy.add(west));
TreeSet<Job> complete = new TreeSet<>(Comparator.comparingInt((Job job) -> job.priority)
.thenComparing(job -> job.receiptId));
complete.add(east); complete.add(west);
System.out.println("lossy=" + lossy.size() + ", complete=" + complete.size());
}
}Output
second accepted=false
lossy=1, complete=2Costs and boundaries
TreeSet offers logarithmic add and lookup in its element count when the comparator behaves correctly. The example proves a collision, not a performance advantage over a hash-based set.
Common Mistakes
- Do not use a partial comparator as a business identity rule.
- Do not assume object equals controls TreeSet uniqueness.
- Do not subtract priorities if overflow is possible.
Read next
Java LinkedHashSet and TreeSet: order and uniqueness, Java comparators: tie-breakers, overflow and sorted-key identity, Java PriorityQueue: define tie order in the comparator.
