23

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

排序代码:

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

FinalSentence 类头:

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

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

这是一个例外:

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)

对于一个小列表(少于 50 个元素)它可以工作。对于一个大列表(它也应该与那些一起工作)它会抛出这个异常。List 的实例类型是 ArrayList,这并不重要。

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

有任何想法吗?

先谢谢了!!!

4

3 回答 3

21

根据OP 的评论我建议使用

Double.compare(score, o.score)

解决了这个问题。我的猜测是±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    }

来源

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


参考:

于 2013-10-04T14:00:13.460 回答
4

如果你打破传递性规则,它可能会发生。如果 A>B 且 B>C,则 C>A 违约

于 2013-10-04T14:25:25.530 回答
-4

你不是说打字吗:

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

而不是这个:

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

?

于 2013-10-04T13:48:41.587 回答