I know this has been an issue for a while now, and checked all previously answers I could get, but still this one doesn't work.
The object 'crew' represents crewmembers with ranks and other items. The comparison should be made by comparing 'assigned_rank', an int value, and if this value is equal in both instances, then 'is_trainer', a boolean, should make the difference.
This method worked great as long as it was running with java < 7. But since Java 7 I keep getting this one:
java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.ComparableTimSort.mergeLo(ComparableTimSort.java:714)
at java.util.ComparableTimSort.mergeAt(ComparableTimSort.java:451)
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)
at dormas_flightlog.Query.getCrew(Query.java:714)
Here is the source, where some potentially dangerous parts have allready been out-commented, but it still does not work:
public class crew implements Serializable, Comparable<crew> {
private static final long serialVersionUID = 36L;
private int flightID = 0;
private int assigned_rank = 25;
private boolean is_trainer = false;
...
@Override
public int compareTo(crew him) {
int myRank = this.getAssigned_rank();
int hisRank = him.assigned_rank;
if (this == him) {
return 0;
}
if (myRank > hisRank) {
return 1;
}
if (myRank < hisRank) {
return -1;
}
if (myRank == hisRank) {
// if (is_trainer && !o.is_trainer) {
// i = 1;
// }
// if (!is_trainer && o.is_trainer) {
// i = -1;
// }
// if (is_trainer && o.is_trainer) {
// i = 0;
// }
// if (!is_trainer && !o.is_trainer) {
// i = 0;
// }
return 0;
}
return 0;
}
@Override
public int hashCode() {
int hash = 7;
hash = 31 * hash + this.assigned_rank;
hash = 31 * hash + (this.is_trainer ? 1 : 0);
return hash;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
int myRank = this.getAssigned_rank();
int hisRank = 0;
if (o instanceof crew) {
crew him = (crew) o;
hisRank = him.assigned_rank;
} else {
return false;
}
if (myRank > hisRank) {
return false;
}
if (myRank < hisRank) {
return false;
}
if (myRank == hisRank) {
// if (is_trainer && !o.is_trainer) {
// i = 1;
// }
// if (!is_trainer && o.is_trainer) {
// i = -1;
// }
// if (is_trainer && o.is_trainer) {
// i = 0;
// }
// if (!is_trainer && !o.is_trainer) {
// i = 0;
// }
return true;
}
return false;
}
}
Implementing equals() was just a try to solve this problem. The given exception comes with or without equals(). I cannot see how the compareTo-method violates its contract. Any help is greatly appreciated....one day this code has to work with java 7 and I don't know how... Thanks
see this:
From http://www.oracle.com/technetwork/java/javase/compatibility-417013.html#source
Area: API: Utilities Synopsis: Updated sort behavior for Arrays and Collections may throw an IllegalArgumentException
Description: The sorting algorithm used by java.util.Arrays.sort and (indirectly) by java.util.Collections.sort has been replaced. The new sort implementation may throw an IllegalArgumentException if it detects a Comparable that violates the Comparable contract. The previous implementation silently ignored such a situation. If the previous behavior is desired, you can use the new system property java.util.Arrays.useLegacyMergeSort, to restore previous mergesort behavior.
Nature of Incompatibility: behavioral
RFE: 6804124
For more detailed info, see the bug database reference here.