Comparable defines a natural order for Java objects through compareTo(). Its result is sign-based: negative means less than, zero equal in ordering, and positive greater than. Implementations need not return only -1, 0, or 1. section 7.9
A valid compareTo() is antisymmetric and transitive. It must return 0 when an object is compared with itself or another object equal in its ordering; when two comparisons return 0, they must have the same comparison sign against every third object. Returning -1 for two wrappers of the same boolean value falsely declares each smaller than itself. section 7.10
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 implementation gets opposite boolean values right but never returns 0 for equal values. Return `b == o.b ? 0 : b ? 1 : -1`, or delegate to `Boolean.compare(b, o.b)`, instead. section 7.10
Use comparison results and alternative orderings defensively:
- Test only the sign of a comparison result. `result == 1` is invalid because a conforming implementation may return any positive value; `String.compareTo()` can do so. section 7.9
- Use a Comparator when the original class cannot be modified or when its natural order is unsuitable. Comparator.compare() follows a similar contract and can explicitly place null values with nullsFirst() or nullsLast(). section 7.10
- Do not assume a content-based compareTo() matches equals() and hashCode(). StringBuilder compares content but retains identity-based equality and hashing, creating risky behavior as a mutable HashSet or HashMap key. section 8.6
Ordering users without assuming exact values
A User natural order can compare names first and ages only when names compare as zero. Comparing Mary, 30 with Mary, 20 may yield 1 through Integer.compare(), while comparing Mary with Joe can yield 3 through String.compareTo(). Both results mean greater than; code that expects exactly 1 can silently process data in the wrong order. section 7.9
Mutable keys are hazardous independently of ordering, but inconsistent comparison can deepen the problem. Since Java 8, heavily collided HashMap or HashSet buckets may use red-black trees and rely on compareTo(); mutating a StringBuilder after insertion can make contains() fail in a demonstrated collision scenario. section 8.6


