比较方法违反了它的一般契约!仅限 Java 7

发布于 2024-12-11 08:14:34 字数 3022 浏览 0 评论 0原文

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

对象“crew”代表具有等级和其他项目的船员。应通过比较 int 值“assigned_rank”来进行比较,如果两个实例中该值相等,则布尔值“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 一起工作,但我不知道如何... 谢谢

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

〆一缕阳光ご 2024-12-18 08:14:34

看到这个:

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

区域:API:实用程序概要:更新了数组和
集合可能会抛出 IllegalArgumentException

描述:java.util.Arrays.sort使用的排序算法和
(间接)被 java.util.Collections.sort 取代。新的
如果排序实现检测到,可能会抛出 IllegalArgumentException
违反可比合同的可比公司。上一个
实施默默地忽略了这种情况。如果之前的
行为是所需的,您可以使用新系统
属性 java.util.Arrays.useLegacyMergeSort,恢复以前的
合并排序行为。

不兼容的性质:行为

RFE:6804124

有关更多详细信息,请参阅错误数据库 参考在这里

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.

纵性 2024-12-18 08:14:34

也许你只是通过Collections.sort(...)比较NaN值,这对我来说是一个问题,即使正确实现了compare(obj1, obj2) 方法!检查一下!

maybe you just have NaN values which you compare through Collections.sort(...), this has been a problem to me and I got that exception even having right implementation of compare(obj1, obj2) method! Check that!

趁年轻赶紧闹 2024-12-18 08:14:34

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

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

“比较方法违反了其一般契约! ” - TimSort 和 GridLayout

基本上我只需将其添加

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

到我的 jboss 中

I was able to solve this error cause it was a bug in jdk7.

here I found the solution:

"Comparison method violates its general contract!" - TimSort and GridLayout

Basically i just had to add the

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

to my jboss

顾北清歌寒 2024-12-18 08:14:34

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

从其他报告来看,这与使用具有重叠项目的relativelayout有关,就像通常所做的那样。例如,出现在图像上方的 TextView,或同一位置的两个项目,其中您一次仅设置一个可见。
https://code.google.com/p/android/issues/详细信息?id=55933

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

有传言称 Java 9 将进行修复,例如有效的运行时选项,但由于存在多年的错误,我怀疑它是否会得到修复 - 特别是考虑到 Oracle 和 Google 之间的敌意。是的,也许这个 bug 在 Android 代码中确实很深,应该在那里修复。现有设备超过十亿,这并不是适用于所有现有设备的可行解决方案。

Unfortunately, none of the solutions work for Android. TimSort is used deep in Android's ViewGroup relating to addChildrenForAccessibility that shows up under Java 7 & 8. No user code is involved in any comparison.

From other reports, it is related to having RelativeLayout with overlapping items as is commonly done. For example, a TextView that appears over an Image, or two items at the same location, where you only set one visible at a time.
https://code.google.com/p/android/issues/detail?id=55933

I've not found any way around the bug. You can't set a -Djava option in Android Studio or Eclipse (at least that I could find). Forcing use of Java 1.6 should work, but doesn't. Seems like Amazon's newer Fire tablets and phones are far more sensitive to this bug than other devices.

There are rumors Java 9 will have a fix such as a run-time option that works, but with a bug that's been around for years, I have doubts it will ever be fixed - especially considering the animosity between Oracle and Google. Any yes, perhaps the bug is really deep in the Android code and should be fixed there. With more than a billion devices out there, that's not a viable solution for all the existing devices.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文