Java Collections.sort() throws 比较方法违反了它的一般约定!例外

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19182700/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 14:50:04  来源:igfitidea点击:

Collections.sort() throws Comparison method violates its general contract! exception

javasortingexceptioncollections

提问by Eugene Krapivin

I'm trying to sort a List<> object and I get this exception thrown (for large lists only though)

我正在尝试对 List<> 对象进行排序,但抛出了此异常(尽管仅适用于大型列表)

sorting code:

排序代码:

List<FinalSentence> sentenceList = finalRepresentation.getSentences();
Collections.sort(sentenceList); // <=== EXCEPTION THROWN HERE!!!

FinalSentence class header:

FinalSentence 类标题:

public class FinalSentence implements Comparable<FinalSentence>{...}

compareTo() implementation:

compareTo() 实现:

@Override
public int compareTo(FinalSentence o) {
    if (this == o) {
        return 0;
    }
    if (this.score > o.score) {
        return 1;
    }
    if (this.score < o.score) {
        return -1;
    }
    return 0;
}

this is the exception:

这是例外:

Exception in thread "main" java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.ComparableTimSort.mergeHi(Unknown Source)
at java.util.ComparableTimSort.mergeAt(Unknown Source)
at java.util.ComparableTimSort.mergeCollapse(Unknown Source)
at java.util.ComparableTimSort.sort(Unknown Source)
at java.util.ComparableTimSort.sort(Unknown Source)
at java.util.Arrays.sort(Unknown Source)
at java.util.Collections.sort(Unknown Source)
at feature.finalRepresentation.Summarizer.summarize(Summarizer.java:30)
at driver.Driver.main(Driver.java:114)

for a small list (less than 50 elements) it works. for a large list (it's supposed to work with those as well) it throws this exception. The instance type of the List is ArrayList, not that it should matter.

对于一个小列表(少于 50 个元素),它可以工作。对于大列表(它也应该与那些列表一起使用),它会引发此异常。List 的实例类型是 ArrayList,它应该无关紧要。

I have no idea how to get to the bottom of this. The list is full, the elements are of the same type (no polymorphism there) and yet I get this weird exception for large lists.

我不知道如何深入了解这一点。列表已满,元素的类型相同(那里没有多态性),但是对于大列表,我得到了这个奇怪的例外。

Any ideas?

有任何想法吗?

Thanks ahead!!!

先谢谢了!!!

采纳答案by arshajii

According to the OP's comment, my suggestionof using

根据OP 的评论我建议使用

Double.compare(score, o.score)

fixed the issue. My guess is that there was either a problem with ±0s or NaNs. In fact, if you look at the source of Double.compare(), you will find that it's slightly more complicated than you might think, and treats these cases specifically:

解决了这个问题。我的猜测是±0s 或NaNs有问题。事实上,如果你查看 的来源Double.compare(),你会发现它比你想象的要稍微复杂一些,并且专门处理这些情况:

958    public static int compare(double d1, double d2) {
959        if (d1 < d2)
960            return -1;           // Neither val is NaN, thisVal is smaller
961        if (d1 > d2)
962            return 1;            // Neither val is NaN, thisVal is larger
963
964        long thisBits = Double.doubleToLongBits(d1);
965        long anotherBits = Double.doubleToLongBits(d2);
966
967        return (thisBits == anotherBits ?  0 : // Values are equal
968                (thisBits < anotherBits ? -1 : // (-0.0, 0.0) or (!NaN, NaN)
969                 1));                          // (0.0, -0.0) or (NaN, !NaN)
970    }

(source)

来源

Moral is: be careful when comparing doubles! :)

道德是:比较双打时要小心!:)



Reference:

参考:

回答by dstronczak

Didn't you mean typing:

你不是说输入:

    if (this.score == o.score) {
        return 0;
    }

instead of this:

而不是这个:

    if (this == o) {
        return 0;
    }

?

?

回答by znat

It could happen if you break the transitivity rule. If A>B and B>C, then C>A breaks the contract

如果您违反传递性规则,则可能会发生这种情况。如果 A>B 且 B>C,则 C>A 违约