JAVA JDK8-Comparsion method violates its general contract
Solution 1
- Add this code into
main()
System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");
- code as below.
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
//system properties---------------------------------------------------
System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");
String fileName = "K2_flu_12062022_20230111_try_correct1.xdsl";
System.out.println("try" + fileName);
runOne(fileName);
System.out.println("finish!");
This will use the old merge sort algorithm instead of TimSort. By using this algorithm, it could bypass the EXCEPTION.
Solution 2
- SepSetComparator need to be modified.
- Comparator must be transitive without a contradiction.
- Compare( ) should follow this rule (https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html)
- add this code to compare()
public int compare(Object o1, Object o2) {
SepSet sepSet1 = (SepSet) o1;
SepSet sepSet2 = (SepSet) o2;
int[] results1 = new int[2];
int[] results2 = new int[2];
results1[0] = -sepSet1.size();
results1[1] = 1;
for (int i = 0; i < sepSet1.size(); i++) {
results1[1] = results1[1] * sepSet1.get(i).getStates().size();
}
results2[0] = -sepSet2.size();
results2[1] = 1;
for (int i = 0; i < sepSet2.size(); i++) {
results2[1] = results2[1] * sepSet2.get(i).getStates().size();
}
// Here is the modifying part.-----------------------------------------------
if (results1[0] < results2[0] || results1[1]<=results2[1]) {
return -1;
}
else if (results1[0] == results2[0] || results1[1]>results2[1]) {
return 0;
}
else {
return 1;
}
//-------------------------------------------------------------------------
}
Explanation
Solution 1
- bypass the exception by using LegacyMergeSort instead of TimSort. [TimSort replaced LegacyMergeSort after JDK 7].
- When do use this solution? If you are sure that your Compare() method is correct, use this solution.
Solution 2
- usually when this exception occur, the comprare method may have not include all conditions.
- Since orignal code is
// Here is the original part.-----------------------------------------------
if (results1[0] < results2[0]) {return -2;}
else if (results1[0] == results2[0]) {
if (results1[1] <= results2[1]) {
return -1;
} else {
return 0; }
}
else {
return 1;
}
Since compare method only return three value: -1,0,1
if you want results1[1]<=results2[1] return -1
. My suggestion is to write this situation together. Thus,
if (results1[0] < results2[0] || results1[1]<=results2[1]) {
return -1;
}
After add this, we still need to consider results1[1]>results2[1] this situation. Thus,
else if (results1[0] == results2[0] || results1[1]>results2[1]) {
return 0;
}
else return 1
Finally, we include all three situation where comparing the list of reuslts1 and reuslts2. The main method should run without exception.
Reference
java.util.TimSort
Similar issue:
- https://bugs.java.com/bugdatabase/view_bug.do?bug_id=7193557
- https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8234482
Comparator:
- https://www.scaler.com/topics/java/comparable-and-comparator-in-java/
- https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html