1. ホーム
  2. ジャワ

javaException: 比較メソッドが一般契約に違反しています!

2022-02-21 03:40:43
<パス

プロジェクトがオンライン稼働中に突然数百通の異常メールが発生し、しばらくすると自動的に正常な状態になりました。
プロジェクトの例外エラーメッセージは
比較方式が一般契約に違反する
スタックを調べた結果、例外を発生させたのはsortのcompareメソッドのオーバーライドであることがわかりました。
Webで情報を調べたり、sortのソースコードを読んだりした結果、次のような結論に達しました。
sortで書き換えたメソッドが満たすべきもの。 可逆的な比較


Comparator<Integer> c = (o1, o2) -> {
    if (o1 > o2) {
        return 1;
    } else {
        return -1;
    }
};



上記のコンパレータは可逆性を満たしていないので、o1とo2が等しいとき、o1とo2を比較して、o1がo2より小さいことを示す-1を返す。しかし、2つの要素が場所を交換したとき、o1よりo2は、結果がo2がo1より小さいことを示すか-1を返す。したがって、o1<o2とo2<o1という2つの要素の入れ替わり比較が存在することになる。 この2つの結果は互いに矛盾しており、場合によっては例外が発生する可能性もある。


解決方法

この問題を本当に解決するには、多くのネット上の書き込みにあるように、単に等号条件を追加すればいいというものではありません。これは逆比較に起因する問題であり、根本的に解決する必要があるのです。
compareメソッドと逆比較を矛盾させる つまり
アド・イコールのケースなのか、それとももっと複雑なケースがあるのかは、それぞれのビジネスによって異なります。


このバグがどのように引き起こされるかを正確に理解するには、JavaのTimSortソートについて以下のサイトを参照してください。 TimSortの説明