14

なぜこのコードは

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() はブール値を返します。

ありがとう。

4

7 に答える 7

27

どちらの値も後援されていない場合に問題が発生すると思われます。それはあなたがそれをどのように呼んでも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。

于 2011-07-08T15:09:16.790 に答える
20

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

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

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

概要:のソート動作を更新ArraysCollectionsIllegalArgumentException

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

非互換性の性質:行動

RFE:6804124

詳細については、こちらのバグデータベースリファレンスを参照してください。

于 2011-12-07T15:07:18.183 に答える
10

equals()とcompareTo()の間の契約は、equals()がtrueを返す場合、compareTo()は0を返し、equals()がfalseの場合、compareToは-1または+1を返す必要があります。

ところで:デバッグメッセージはかなりの量のCPUとメモリを消費するため、compare()メソッドはあまり頻繁に呼び出されないと思います。

于 2011-07-08T15:16:15.653 に答える
1

私はすべての回答に特別にジョンに同意しましたが、メソッドが決して壊れないように比較メソッドでnullの安全性を常にチェックする必要があることを伝えたいと思います。詳細については、こちらをご覧ください

于 2014-07-24T14:59:57.400 に答える
0

今日、Web アプリケーションで同じ問題が発生しました。同じ配列で動作している 4 つの呼び出しが同時に並べ替えを試みたため、互いに混乱していました。

于 2016-10-21T13:34:31.130 に答える
0

Collections.sort を介して比較する NaN 値を持っているだけかもしれません...これは私にとって問題でした。それを確認します!

于 2013-03-29T13:24:57.113 に答える