Can someone explain me in simple terms, why does this code throw an exception, “Comparison method violates its general contract!”, and how do I fix it?
private int compareParents(Foo s1, Foo s2) {
if (s1.getParent() == s2) return -1;
if (s2.getParent() == s1) return 1;
return 0;
}
Your comparator is not transitive.
Let
Abe the parent ofB, andBbe the parent ofC. SinceA > BandB > C, then it must be the case thatA > C. However, if your comparator is invoked onAandC, it would return zero, meaningA == C. This violates the contract and hence throws the exception.It’s rather nice of the library to detect this and let you know, rather than behave erratically.
One way to satisfy the transitivity requirement in
compareParents()is to traverse thegetParent()chain instead of only looking at the immediate ancestor.