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?
pri
You can't compare object data like this:s1.getParent() == s2
- this will compare the object references. You should override equals function
for Foo class and then compare them like this s1.getParent().equals(s2)
In our case were were getting this error because we had accidentally flipped the order of comparison of s1 and s2. So watch out for that. It was obviously way more complicated than the following but this is an illustration:
s1 == s2
return 0;
s2 > s1
return 1;
s1 < s2
return -1;
If compareParents(s1, s2) == -1
then compareParents(s2, s1) == 1
is expected. With your code it's not always true.
Specifically if s1.getParent() == s2 && s2.getParent() == s1
.
It's just one of the possible problems.
I've seen this happen in a piece of code where the often recurring check for null values was performed:
if(( A==null ) && ( B==null )
return +1;//WRONG: two null values should return 0!!!
Even if your compareTo is holds transitivity in theory, sometimes subtle bugs mess things up... such as floating point arithmetic error. It happened to me. this was my code:
public int compareTo(tfidfContainer compareTfidf) {
//descending order
if (this.tfidf > compareTfidf.tfidf)
return -1;
else if (this.tfidf < compareTfidf.tfidf)
return 1;
else
return 0;
}
The transitive property clearly holds, but for some reason I was getting the IllegalArgumentException. And it turns out that due to tiny errors in floating point arithmetic, the round-off errors where causing the transitive property to break where they shouldn't! So I rewrote the code to consider really tiny differences 0, and it worked:
public int compareTo(tfidfContainer compareTfidf) {
//descending order
if ((this.tfidf - compareTfidf.tfidf) < .000000001)
return 0;
if (this.tfidf > compareTfidf.tfidf)
return -1;
else if (this.tfidf < compareTfidf.tfidf)
return 1;
return 0;
}