I'm attempting to sort a collection and getting the following exception:
java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.ComparableTimSort.mergeHi(ComparableTimSort.java:835)
at java.util.ComparableTimSort.mergeAt(ComparableTimSort.java:453)
at java.util.ComparableTimSort.mergeCollapse(ComparableTimSort.java:376)
at java.util.ComparableTimSort.sort(ComparableTimSort.java:182)
at java.util.ComparableTimSort.sort(ComparableTimSort.java:146)
at java.util.Arrays.sort(Arrays.java:472)
at java.util.Collections.sort(Collections.java:155)
I'm aware of the 3 contracts for compareTo:
- x.compareTo(y)>0 && y.compareTo(z)>0) implies x.compareTo(z)>0
- sgn(x.compareTo(y)) == -sgn(y.compareTo(x))
- x.compareTo(y)==0 implies that sgn(x.compareTo(z)) == sgn(y.compareTo(z))
The code is below. I can see that there is potential for the Long.intValue() to be truncated, but as far as i can see this should not violate the contract.
public class Bar implements Comparable<Bar>{
private static final int LOWER = 1;
private static final int HIGHER = -1;
private boolean isNoPriority;
private int priority;
private String tradeId;
private long tradeVersion;
public Bar(boolean isNoPriority, int priority, String tradeId,long tradeVersion) {
super();
this.isNoPriority = isNoPriority;
this.priority = priority;
this.tradeId = tradeId;
this.tradeVersion = tradeVersion;
}
@Override
public int compareTo(Bar o) {
if (isNoPriority && !o.isNoPriority){
return LOWER;
}
if (!isNoPriority && o.isNoPriority){
return HIGHER;
}
if (priority == o.priority) {
if (tradeId.compareToIgnoreCase(o.tradeId) == 0){
return Long.valueOf(tradeVersion).intValue() - Long.valueOf(o.tradeVersion).intValue();
}
else {
return tradeId.compareToIgnoreCase(o.tradeId);
}
}
else if (priority < o.priority) {
return LOWER;
}
else if (priority > o.priority){
return HIGHER;
} else {
return 0;
}
}
}
I cannot understand what is incorrect about this compareTo implementation.