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
Collections.sort() throws Comparison method violates its general contract! exception
提问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
Double.compare(score, o.score)
fixed the issue. My guess is that there was either a problem with ±0
s or NaN
s. 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:
解决了这个问题。我的猜测是±0
s 或NaN
s有问题。事实上,如果你查看 的来源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 违约