37

我知道这个问题已经有一段时间了,并检查了我能得到的所有以前的答案,但是这个仍然不起作用。

对象“船员”代表具有等级和其他物品的船员。应该通过比较'assigned_rank',一个int值来进行比较,如果这个值在两个实例中相等,那么'is_trainer',一个布尔值,应该会有所不同。

只要使用 java < 7 运行,此方法就可以很好地工作。但是自从 Java 7 以来,我一直得到这个:

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)

这是源代码,其中一些潜在危险的部分已经被注释掉了,但它仍然不起作用:

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;
}

}

实现 equals() 只是为了解决这个问题。给定的异常带有或不带有 equals()。我看不到 compareTo 方法是如何违反其合同的。非常感谢任何帮助....有一天这段代码必须与 java 7 一起使用,我不知道如何...谢谢

4

4 回答 4

48

看到这个:

来自http://www.oracle.com/technetwork/java/javase/compatibility-417013.html#source

领域:API:实用程序概要:更新了数组和集合的排序行为可能会引发 IllegalArgumentException

说明:java.util.Arrays.sort 和(间接)java.util.Collections.sort 使用的排序算法已被替换。如果新的排序实现检测到违反 Comparable 合同的 Comparable,它可能会抛出 IllegalArgumentException。之前的实现默默地忽略了这种情况。如果需要之前的行为,您可以使用新的系统属性 java.util.Arrays.useLegacyMergeSort 来恢复之前的合并排序行为。

不兼容的性质:行为

射频:6804124

有关更多详细信息,请参阅此处的错误数据库参考

于 2011-12-07T15:02:37.890 回答
10

也许你只是有NaN你比较的值Collections.sort(...),这对我来说一直是个问题,即使有正确的方法实现我也得到了那个例外compare(obj1, obj2)!检查那个!

于 2013-03-29T13:19:07.447 回答
4

我能够解决这个错误,因为它是 jdk7 中的一个错误。

在这里我找到了解决方案:

“比较法违反了它的总契约!” - TimSort 和 GridLayout

基本上我只需要添加

JAVA_OPTS="$JAVA_OPTS -Djava.util.Arrays.useLegacyMergeSort=true"

给我的老板

于 2015-03-12T22:23:37.447 回答
0

不幸的是,没有一个解决方案适用于 Android。TimSort 在 Android 的 ViewGroup 中深入使用,与 Java 7 和 8 下显示的 addChildrenForAccessibility 相关。任何比较均不涉及用户代码。

从其他报告来看,这与通常使用的具有重叠项目的 RelativeLayout 有关。例如,出现在 Image 上的 TextView 或同一位置的两个项目,您一次只能设置一个可见。 https://code.google.com/p/android/issues/detail?id=55933

我还没有找到解决该错误的任何方法。您不能在 Android Studio 或 Eclipse 中设置 -Djava 选项(至少我能找到)。强制使用 Java 1.6 应该可以,但不能。似乎亚马逊较新的 Fire 平板电脑和手机对这个漏洞比其他设备敏感得多。

有传言称 Java 9 将有一个修复程序,例如运行时选项,但由于一个已经存在多年的错误,我怀疑它是否会被修复——尤其是考虑到甲骨文和谷歌之间的敌意。任何是的,也许这个错误在Android代码中真的很深,应该在那里修复。有超过 10 亿台设备,对于所有现有设备来说,这并不是一个可行的解决方案。

于 2017-03-08T22:50:08.130 回答