Card 07/ 09

GotchaDifficulty: Advanced1 min

Why Your Sort Threw Comparison Method Violates Its General Contract

A sort that has always worked throws, on a particular list, with a message about a contract nobody remembers agreeing to. The same comparator on a shorter list is fine.

text
Exception in thread "main" java.lang.IllegalArgumentException: Comparison method violates its general contract!

Java's sort assumes the comparator is consistent, and it checks that assumption while it works. Three things have to hold for every pair and triple it is given.

What a comparator has to guarantee
RuleMeans
AntisymmetryIf compare(a, b) is negative, compare(b, a) is positive
TransitivityIf a is before b and b is before c, then a is before c
Consistent tiesIf a and b tie, they compare the same way against every c

The two usual causes are the overflow from subtracting, and a comparator that returns zero for pairs it cannot decide between while ordering them differently through some other route. Both break transitivity, and neither shows up until the sort happens to compare the offending triple.

Build comparators from Comparator.comparing and thenComparing rather than writing the arithmetic. Those combinators are consistent by construction, and the contract stops being something you have to remember.