A comparison method—Comparator.compare or Comparable.compareTo—determines the ordering relationship between two values. Its result is interpreted by sign: negative means before, zero means equivalent in ordering, and positive means after. Code must not require an exact result such as -1 or 1; implementations may return any negative or positive number. section 7.9
The safest implementation represents each object as an ordered sequence of keys. Compare the first key, continue only when it is equal, and use later keys as tie-breakers. This avoids asymmetric special cases and preserves distinctions between objects. section 7.13
Avoid these common comparison-method failures:
- Do not return a fixed result merely because one object has a special property. Compare that property as a key, then compare the remaining keys. section 7.13
- Handle nullable keys explicitly. Comparing nullity first and the value second prevents unrelated objects from being reported as equal. section 7.13
- Test sign comparisons with < 0, == 0, and > 0 rather than comparing the result with a particular nonzero constant. section 7.9
A robust multi-key order
For a person ordered by name and then age, compare name first and age only when names match. Comparator.comparing(...).thenComparing(...) expresses this structure directly. section 7.13
public int compareTo(Connection that) {
int res = Boolean.compare(
that instanceof SecureConnection,
this instanceof SecureConnection);
if (res != 0) return res;
return this.url.compareTo(that.url);
}
Compare the secure-connection flag as the first key, then compare URLs; this corrects the special-case implementation. section 7.13
public int compareTo(User o) {
int res = Boolean.compare(name == null, o.name == null);
if (res != 0) return res;
return name != null ? name.compareTo(o.name) : 0;
}
Compare whether names are null before comparing non-null names, establishing a consistent null ordering. section 7.13
