Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Comparison method violates its general contract! Java 7 only

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

like image 739
user1007068 Avatar asked Oct 21 '11 12:10

user1007068


1 Answers

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.

like image 96
naresh Avatar answered Sep 29 '22 10:09

naresh