5

この例外に関する他の質問を見てきましたが、私の比較方法は非常に単純であるため、何が問題なのかを理解できず、所有しているどの Android デバイスでも再現できません。

Android アプリの一部のユーザーからこの例外が発生しています。そのほとんどは、マージ ソートの Java 7 バリアントを実行していると思われる GS3 や GS4 などの非常に新しいデバイスにあるようです。

これが私の比較方法です:

            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に仕事をさせるべきだと信じています。

2 つの Double オブジェクトを数値的に比較します。

このメソッドによって実行される比較が、Java 言語の数値比較演算子 (<、<=、==、>=、>) によって実行される比較と異なる点が 2 つあります (プリミティブ double 値に適用される場合)。

  1. このメソッドでは、Double.NaN はそれ自体と等しく、他のすべての double 値 (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 クラスの 2 つのインスタンス d1 と d2 の場合、d1.equals(d2) の値は、d1.doubleValue() == d2.doubleValue() の場合にのみ true になります。

値も true です。ただし、次の 2 つの例外があります。

d1 と d2 の両方が Double.NaN を表す場合、Double.NaN==Double.NaN の値が false であっても、equals メソッドは true を返します。d1 が +0.0 を表し、d2 が -0.0 を表す場合、またはその逆の場合、+0.0==-0.0 の値が true であっても、等しいテストの値は false になります。

于 2013-07-15T16:39:32.507 に答える
2

2 つの Double オブジェクトを比較する代わりに、実際にはそれらのを比較する必要があります( getDoubleValue())。2 つのオブジェクトを比較しても、それらの値が等しいとは限りません。

于 2013-07-15T16:39:24.047 に答える