简体   繁体   English

使用Math.abs(diff)排序时出现Java意外的IllegalArgumentException

[英]Java unexpected IllegalArgumentException in sorting with Math.abs(diff)

I have some behaviour I didn't expect concerning when sorting a list of Doubles. 在对双打列表进行排序时,我有一些我没想到的行为。 The goal I have is to sort a list of doubles, but when the two doubles are near each other, then I don't care about their order (in reality, I use an Entry<> with a Double as the value, and when the two Double values are close, I sort on something else. 我的目标是对双打列表进行排序,但是当两个双打彼此靠近时,我不在乎它们的顺序(实际上,我使用Entry <>并将Double作为值,当两个Double值很接近,我在其他方面进行了排序。

Here is a sample that will throw an IllegalArgumentException: 这是一个将抛出IllegalArgumentException的示例:

public static void main(String[] args) {
    final float probabilitySortMargin = 0.2f;
    Comparator<Double> comp = new Comparator<Double>() {
        @Override
        public int compare(Double o1, Double o2) {
            // sort on probability first
            double diff = Math.abs(o1 - o2);
            if(diff > probabilitySortMargin)
                // difference is more than desired range, sort descending
                return Double.compare(o2 , o1);
            return 0;
        }
    };

    ArrayList<Double> vals = new ArrayList<>();
    Random r = new Random(0);
    for(int i=0;i<1000;i++)
        vals.add(r.nextDouble());

    for(int i=0;i<vals.size();i++)
        for(int j=0;j<vals.size();j++)
            if(comp.compare(vals.get(i), vals.get(j)) != -1 * comp.compare(vals.get(j), vals.get(i)))
                System.out.println("Comparison failed");

    Collections.sort(vals, comp);
}

which results in 导致

Exception in thread "main" java.lang.IllegalArgumentException: Comparison method violates its general contract!
    at java.util.TimSort.mergeHi(TimSort.java:899)
    at java.util.TimSort.mergeAt(TimSort.java:516)
    at java.util.TimSort.mergeCollapse(TimSort.java:441)
    at java.util.TimSort.sort(TimSort.java:245)
    at java.util.Arrays.sort(Arrays.java:1512)
    at java.util.ArrayList.sort(ArrayList.java:1462)
    at java.util.Collections.sort(Collections.java:175)
    at some.package.Sample.main(Sample.java:10)

Why is this happening? 为什么会这样呢? Even weirder, the error message "Comparison failed" is NOT printed. 即使很奇怪,也不会打印错误消息“比较失败”。

Your compare method does violate the contract of the Comparator interface. 您的compare方法确实违反了Comparator接口的约定。

the implementor must ensure that compare(x, y)==0implies that sgn(compare(x, z))==sgn(compare(y, z)) for all z. 实现者必须确保compare(x,y)== 0意味着所有z的sgn(compare(x,z))== sgn(compare(y,z))。

compare(0.1,0.2) == 0, but sgn(compare(0.1,0.35)) != sgn(compare (0.2,0.35))

"Comparison failed" is never printed because your method doesn't violate the sgn(compare(x, y)) ==-sgn(compare(y, x)) requirement. 绝不会打印“比较失败”,因为您的方法没有违反sgn(compare(x, y)) ==-sgn(compare(y, x))要求。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM