5

我已经看到有关此异常的其他问题,但我的比较方法非常简单,以至于我无法弄清楚它有什么问题,而且我无法用我拥有的任何 Android 设备重现它。

我从我的 Android 应用程序的一些用户那里得到了这个例外,其中大部分似乎都在非常新的设备上,比如 GS3 或 GS​​4,我猜它们运行的​​是合并排序的 Java 7 变体。

这是我的比较方法:

            Collections.sort(collectionOfThings, new Comparator<Thing>()
            {
                public int compare(Thing lhs, Thing rhs) 
                {
                    //getDist() returns a Double with a capital D...perhaps that has something to do with it?
                    if(lhs.getDist() < rhs.getDist())
                    {
                        return -1;
                    }
                    if(lhs.getDist() == rhs.getDist())
                    {
                        return 0;
                    }

                    return 1;
                };
            });

这是一个例外:

Caused by: java.lang.IllegalArgumentException: Comparison method violates its general contract!
    at java.util.TimSort.mergeLo(TimSort.java:743)
    at java.util.TimSort.mergeAt(TimSort.java:479)
    at java.util.TimSort.mergeCollapse(TimSort.java:404)
    at java.util.TimSort.sort(TimSort.java:210)
    at java.util.TimSort.sort(TimSort.java:169)
    at java.util.Arrays.sort(Arrays.java:2038)
    at java.util.Collections.sort(Collections.java:1891)

似乎仅限于Android 4.0+。任何帮助是极大的赞赏。

4

2 回答 2

9

重新发明轮子没有用。我相信您应该返回lhs.getDist().compareTo(rhs.getDist());并让提供的实现compareTo完成这项工作。

以数字方式比较两个 Double 对象。

在应用于原始双精度值时,此方法执行的比较与 Java 语言数值比较运算符(<、<=、==、>=、>)执行的比较有两种不同之处:

  1. 此方法认为 Double.NaN 等于其自身并且大于所有其他双精度值(包括 Double.POSITIVE_INFINITY)。

  2. 此方法认为 0.0d 大于 -0.0d。

这确保了此方法强加的 Double 对象的自然排序与 equals 一致。

我相信你得到这个例外,因为你目前的实现可能不适合处理Double.NaNpositive/negative zero重视,但遵守一般合同。查看OpenJDK Double#compare(double,double)源代码:

public static int More ...compare(double d1, double d2) {
   if (d1 < d2)
        return -1;           // Neither val is NaN, thisVal is smaller
    if (d1 > d2)
        return 1;            // Neither val is NaN, thisVal is larger

    long thisBits = Double.doubleToLongBits(d1);
    long anotherBits = Double.doubleToLongBits(d2);

    return (thisBits == anotherBits ?  0 : // Values are equal
            (thisBits < anotherBits ? -1 : // (-0.0, 0.0) or (!NaN, NaN)
             1));                          // (0.0, -0.0) or (NaN, !NaN)
}

还要阅读Double#equals()的文档

请注意,在大多数情况下,对于 Double 类的两个实例 d1 和 d2,当且仅当 d1.doubleValue() == d2.doubleValue() 时 d1.equals(d2) 的值才为真

也有值 true。但是,有两个例外:

如果 d1 和 d2 都表示 Double.NaN,则 equals 方法返回 true,即使 Double.NaN==Double.NaN 的值为 false。如果 d1 表示 +0.0 而 d2 表示 -0.0,或者反之亦然,则相等测试的值为 false,即使 +0.0==-0.0 的值为 true。

于 2013-07-15T16:39:32.507 回答
2

而不是比较两个 Double 对象,您应该真正比较它们的( getDoubleValue())。比较两个对象不一定意味着它们的值相等。

于 2013-07-15T16:39:24.047 回答