Search code examples
javacomparatorcomparable

Contracts of the compare and compareTo method from Comparator and Comparable


When implementing the Comparator and Comparable interfaces, is it required to ensure that:

If

  • x.compare(Object obj1, Object obj2) == x.compare(Object obj3, Object obj2)

or

  • obj1.compareTo(obj2) == obj3.compareTo(obj2) ,

then obj1.equals(obj3) must be true?


Solution

  • Not necessarily.

    What you're describing is the transitive relation between three given objects, and as far as both of the interfaces are concerned, the relationship while using them must be transitive between them.

    This is to say, given three classes A, B, and C that are comparable amongst each other, if A.compareTo(B) == 0 && B.compareTo(C) == 0, then A.compareTo(C) == 0. The same principle applies for Comparator.

    What you're now conflating is the difference between compareTo and equals. While these two are closely related, there isn't anything to enforce the very strong recommendation provided in the documentation:

    It is strongly recommended, but not strictly required that (x.compareTo(y)==0) == (x.equals(y)). Generally speaking, any class that implements the Comparable interface and violates this condition should clearly indicate this fact. The recommended language is "Note: this class has a natural ordering that is inconsistent with equals."

    It is certainly possible and valid to have an equals definition inconsistent with compareTo or even compare, but depending on the nature of the program, it can lead to obscure bugs. If you find yourself in a situation in which you need to rely on both equals and compareTo (or compare), document it and be consistent with its usage.