Comparison method violates its general contract! - TimSort and GridLayout
It seems to me like you've hit a bug in the JDK since the error seems to come from Swing classes.
Options:
Define the property
java.util.Arrays.useLegacyMergeSort
astrue
. Either using in your code the lineSystem.setProperty("java.util.Arrays.useLegacyMergeSort", "true");
before any Swing code. As the first line in the
main
method should work.Or adding
-Djava.util.Arrays.useLegacyMergeSort=true
to your starting options (in the console, or in the project properties in an IDE, Ant script, etc.)
Upgrade your JDK and see if the problem goes away
- Downgrade to Java 6
Comparison method violates its general contract - how to avoid it
Your comparator doesn't deal with nulls and unparseable dates correctly. Consider the following case:
Suppose you have two non null dates d1 and d2 and a null d3.
Suppose d1 > d2.
You thus have
d1 > d2
d1 == d3
d2 == d3
So, if d1 and d2 are both equal to d3, they should also be equal to each other, but they're not.
Start by transforming all your strings to dates or null.
Then use a comparator which considers all null values as bigger (or lower) than all non null values. Comparator
has utility methods to transform a comparator of non-null objects into a comparator which deals with nulls by putting them all first or last.
Java error: Comparison method violates its general contract
The exception message is actually pretty descriptive. The contract it mentions is transitivity: if A > B
and B > C
then for any A
, B
and C
: A > C
. I checked it with paper and pencil and your code seems to have few holes:
if (card1.getRarity() < card2.getRarity()) {
return 1;
you do not return -1
if card1.getRarity() > card2.getRarity()
.
if (card1.getId() == card2.getId()) {
//...
}
return -1;
You return -1
if ids aren't equal. You should return -1
or 1
depending on which id was bigger.
Take a look at this. Apart from being much more readable, I think it should actually work:
if (card1.getSet() > card2.getSet()) {
return 1;
}
if (card1.getSet() < card2.getSet()) {
return -1;
};
if (card1.getRarity() < card2.getRarity()) {
return 1;
}
if (card1.getRarity() > card2.getRarity()) {
return -1;
}
if (card1.getId() > card2.getId()) {
return 1;
}
if (card1.getId() < card2.getId()) {
return -1;
}
return cardType - item.getCardType(); //watch out for overflow!
“Comparison method violates its general contract!”
Both these cases are problematic.
if (lhs == null || rhs == null) return 0;
If you have [123, null, 234]
, then you compare 123
as equal to null
, null
as equal to 234
, and by transitivity you should get 123
equals 234
. But that is not what your comparator returns.
The solution here would be to either disallow null
or sort all nulls
to the bottom (or top), i.e. only return 0
is both are null
, otherwise return 1
or -1
(depending on the null
being left or right).
return (int) (lhs.mTaskInfo.time - rhs.mTaskInfo.time);
Consider comparing Integer.MAX_VALUE + 1
to 0
. The difference between the two is Integer.MAX_VALUE + 1
. Casting this to int
wraps to Integer.MIN_VALUE
. The opposite comparison should then give you - Integer.MIN_VALUE
, but that is Integer.MIN_VALUE
again due to overflow.
The solution here is to use Long.compare(a,b)
.
Related Topics
Facebook Offline Access Step-By-Step
How to Deserialize Js Date Using Jackson
Differencebetween an Ordered and a Sorted Collection
Why Does My Spring Boot App Always Shutdown Immediately After Starting
Passing Pointers Between C and Java Through Jni
Hash String via Sha-256 in Java
Why Do We Need Interfaces in Java
Why Does "Split" on an Empty String Return a Non-Empty Array
Get First Date of Current Month in Java
No Exception While Type Casting with a Null in Java
How to Specify the Root Context in Your <Web-App> Tags in Web.Xml
How to Update a Broadcast Variable in Spark Streaming
Disable Spring Security for Options Http Method
How to Enable Commit on Focuslost for Tableview/Treetableview