コンパレータの例外です。比較メソッドは一般契約に違反する!
2022-02-25 02:35:25
最近、ソート用のコンパレータを書いていて、次のような例外に遭遇しました。
java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeHi(TimSort.java:868)
at java.util.TimSort.mergeAt(TimSort.java:485)
at java.util.TimSort.mergeCollapse(TimSort.java:408)
at java.util.TimSort.sort(TimSort.java:214)
at java.util.TimSort.sort(TimSort.java:173)
at java.util.Arrays.sort(Arrays.java:659)
at java.util.Collections.sort(Collections.java:217)
自作のコードは大まかに以下のように示され、主な機能は取得したファイルを時間順に並べることです。
public ArrayList<File> getAllLogFiles(int flag) {
ArrayList<File> fileList = new ArrayList<File>();
//Omit the logic to get File
........
if (fileList.size() > 1) {
//Comparator, determines result based on time
Collections.sort(fileList, new Comparator<File>() {
@Override
public int compare(File lFile, File rFile) {
long val = lFile.lastModified() - rFile.lastModified();
if (val > 0) {
return -1;
} else if (val == 0L) {
return 0;
}
return 1;
}
});
}
return fileList;
}
その例外メッセージを検索してみると、コンパレータの書き方が悪いことが原因であることがわかりました。
Javaのコンパレータには、"consistency"の原則と呼ばれるものがあり、おそらくこのような仕組みになっているのでしょう。
したがって、コンパレータを記述する際には、すべてのケースを考慮する必要がある。
上記のコードが例外を投げる理由は、lFileまたはrFileがNULLの場合を考慮していないためです。
この2つのパラメーターがNULLでないことは保証できたのですが、JVMはそれを知らないので、コンパレーターのロジックに、以下のような厳密さが要求されました。
の大きさをその都度判断する原則を厳密に考慮した。
この問題では、以下のコードを以下のように変更することができます。
public ArrayList<File> getAllLogFiles(int flag) {
ArrayList<File> fileList = new ArrayList<File>();
//Omit the logic to get File
........
if (fileList.size() > 1) {
ArrayList<File> tmpList = new ArrayList<File>(fileList);
try {
Collections.sort(tmpList, new Comparator<File>() {
@Override
public int compare(File lFile, File rFile) {
boolean lInValid = (lFile == null || !lFile.exists());
boolean rInValid = (rFile == null || !rFile.exists());
boolean bothInValid = lInValid && rInValid;
if (bothInValid) {
return 0;
}
if (lInValid) {
return 1;
}
if (rInValid) {
return -1;
}
Long lTime = lFile.lastModified();
Long rTime = rFile.lastModified();
return lTime.compareTo(rTime) * (-1);
}
});
fileList = tmpList;
//lastModified may meet ErrnoException and return 0
//which may cause "Comparison method violates its general contract!"
} catch (IllegalArgumentException e) {
.........
//active caught the exception
//mainly when getting the file modification time, it may cause ErrnoException, which makes the comparator violates "Consistency" principle
}
}
return fileList;
}
関連
-
Androidアップグレード/ブラシ戦略(GoogleネイティブシステムPixel)
-
Android Studioプロジェクトをインポートすると、無効なgradle jdkコンフィギュレーションが見つかったと報告される
-
-bash : gradlew コマンドが見つかりません。
-
Android 開発 キーボード イベント モバイル ミッキーマウス ケース
-
Android.view.InflateException: バイナリ XML ファイルの行番号 0: クラス <unknown> を展開する際のエラー 解決方法
-
APKのインストール: 失敗 [INSTALL_PARSE_FAILED_NO_CERTIFICATES]
-
Error:Execution failed for task ':app:processDebugResources'. に対する解決策は
-
Android View Bindingの使い方入門
-
再試行したい場合は、手動で adb.exe を kill し、'restart' をクリックしてください。
-
アンドロイドスタジオに角丸ボタンが実装される
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
よくあるJavaのエラー50選(その1)
-
エラー:SSLピアが正しくシャットダウンされない
-
AndroidにおけるActivity/ActionBarActivity/AppCompatActivityの区別と理解について
-
テスト、Eclipseは "エラーが発生しました、詳細はエラーログを参照してください。 java.lang.NullPointerException" を報告します。
-
Android ビューの階層構造
-
Android studioでTextViewのフォントを変更する2つの方法(例:模造歌、公式スクリプト)。
-
二次元コード読み取り機能のAndroid実装(a) - ZXingプラグインアクセス
-
Androidネットワークフレームワーク Volley
-
Android Studio Tips
-
progressBarを使ってロードアニメーションとロードプログレスバーを実装する - 白人の必須アイテム (V)