web-dev-qa-db-ja.com

比較メソッドが例外をスローするのはなぜですか-比較メソッドはその一般的な契約に違反しています!

このコードはなぜですか

public class SponsoredComparator implements Comparator<SRE> {

    public boolean equals(SRE arg0, SRE arg1){
        return arg0.getSponsored()==arg1.getSponsored();
    }

    public int compare(SRE object1, SRE object2) {
        Log.d("SponsoredComparator","object1.getName() == "+ object1.getName());
        Log.d("SponsoredComparator","object1.getSponsored() == "+ object1.getSponsored());
        Log.d("SponsoredComparator","object2.getName() == "+ object2.getName());
        Log.d("SponsoredComparator","object2.getSponsored() == "+ object2.getSponsored());
        Log.d("SponsoredComparator","compare return == "+ (object1.getSponsored() && object2.getSponsored() ? 0 : object1.getSponsored() ? -1 : 1));
        return object1.getSponsored() && object2.getSponsored() ? 0 : object1.getSponsored() ? -1 : 1;
    }
}

この例外をスローします:ERROR/AndroidRuntime(244): Java.lang.IllegalArgumentException: Comparison method violates its general contract!
ERROR/AndroidRuntime(4446): at Java.util.TimSort.mergeLo(TimSort.Java:743)

メソッドsre.getSponsored()はブール値を返します。

ありがとう。

14
lost baby

どちらでもない値が後援されている場合に問題が発生すると思われます。それはあなたがそれをどのように呼んでも1を返します。

x1.compare(x2) == 1

x2.compare(x1) == 1

それは無効です。

これを変更することをお勧めします:

object1.getSponsored() && object2.getSponsored()

object1.getSponsored() == object2.getSponsored()

両方の場所で。私はおそらく実際にはこれをどこかにこのシグネチャを持つメソッドから抽出します:

public static int compare(boolean x, boolean y)

そしてそれをこのように呼びます:

public int compare(SRE object1, SRE object2) {
    return BooleanHelper.compare(object1.getSponsored(), object2.getSponsored());
}

これにより、コードがより明確になります、IMO。

27
Jon Skeet

JDK7を使用していると想定しています。次のURLを確認してください。

から http://www.Oracle.com/technetwork/Java/javase/compatibility-417013.html#source

エリア:API:ユーティリティ

概要:ArraysおよびCollectionsのソート動作が更新されてIllegalArgumentExceptionがスローされる場合があります

説明:Java.util.Arrays.sortおよび(間接的に)Java.util.Collections.sortによって使用されるソートアルゴリズムは置き換えられました。新しいソート実装は、IllegalArgumentExceptionコントラクトに違反するComparableを検出した場合、Comparableをスローする可能性があります。以前の実装では、このような状況を黙って無視していました。以前の動作が必要な場合は、新しいシステムプロパティJava.util.Arrays.useLegacyMergeSortを使用して、以前のマージソート動作を復元できます。

非互換性の性質:行動

RFE:6804124

詳細については、バグデータベースを参照してください ここを参照

19
naresh

私は特にjonとすべての回答に同意しましたが、私たちのメソッドが壊れないように、compareメソッドで常にnullの安全性をチェックする必要があり、常にnullチェックをプログラミングするのは良い習慣です。詳細については、 ここ を参照してください

1
kailash gaur

たぶん、Collections.sortを介して比較するNaN値があるだけです...これは私にとって問題であり、compare(obj1、obj2)メソッドを正しく実装していても例外が発生しました!それを確認します!

0
user2224499

今日、Webアプリケーションで同じ問題が発生しました。同じ配列で動作する4つの呼び出しが同時に配列をソートしようとし、事実上互いに混乱しました。

0
Bjarne Havnen

私の解決策:数値を並べ替えたいときに配列要素がnullの場合、0を入力すると、エラーが消えます。 2次元配列の各行のサイズが同じになるように注意する必要があります。