compareTo defines an object's natural order through Comparable. Its result is negative, zero, or positive when the receiver is respectively smaller than, equal to, or greater than another object. The exact nonzero value is not meaningful: callers must test its sign, not assume that every implementation returns -1 or 1. Sorting algorithms and ordered data structures depend on this contract, so a plausible-looking implementation can cause failures far from the comparison code. section 7.0 section 7.9
A valid implementation is antisymmetric and transitive. Reversing operands must reverse the result's sign, comparing an object with itself must return 0, and comparisons that report equality must behave identically relative to every third object. Returning -1 for two equal boolean wrappers, for example, says that an object is smaller than itself. Such errors can survive simple tests before breaking sorting or ordered-set behavior. section 7.10 section 7.11
class BoolObj implements Comparable<BoolObj> {
final boolean b;
BoolObj(boolean b) { this.b = b; }
@Override
public int compareTo(BoolObj o) {
return b && !o.b ? 1 : -1;
}
}
This compact implementation distinguishes true from false but never returns 0. Comparing two wrappers with the same value therefore violates the Comparable contract; test equal operands as well as opposite ones. section 7.10
Implement natural order defensively:
- Return 0 when all ordering keys are equal. For a boolean key, use Boolean.compare rather than hand-written branches. section 7.10
- Never subtract integer fields to compare them. Overflow can reverse an ordering and violate transitivity; use Integer.compare instead. section 7.11
- Compare multi-field objects as an ordered sequence of keys, stopping at the first difference. section 7.13
- Handle nullable keys as an ordering key too, or delegate to a comparator using nullsFirst or nullsLast. section 7.10 section 7.13
- Prefer Comparator.comparing and thenComparing, or a delegated comparator, when they make the key sequence clearer and reduce manual branches. section 7.13 section 7.15
Compare numeric fields without overflow
Avoid `return i - other.i;`: large values of opposite signs can overflow and make a larger value appear smaller. Use `return Integer.compare(i, other.i);`. For several keys, compare the first key; only if it is equal, compare the next. This preserves the intended lexicographic order and avoids special-case branches that forget equal operands. section 7.11 section 7.13
compareTo is not interchangeable with equals. BigDecimal.compareTo returns 0 for numerically equal values regardless of scale, whereas BigDecimal.equals also compares scale. Conversely, StringBuilder can compare content through compareTo while retaining identity-based equals and hashCode. Choose the comparison relation required by the operation, and avoid mutating keys held in sets or maps when their comparison behavior may be used. section 7.4 section 8.6
A malformed comparison method may trigger `IllegalArgumentException` during sorting, but it can also silently produce incorrect order or make ordered collections fail to find elements. Static analysis and tests help, yet focused tests should include equal values, reversed operands, triples that exercise transitivity, null cases when supported, and extreme numeric values. section 7.11 section 7.9
