単純なコンパレーターが壊れているのはなぜですか?
質問
クラスがあり、これを単純化しています:
final class Thing {
private final int value;
public Thing(int value) {
this.value = value;
}
public int getValue() {
return value;
}
@Override public String toString() {
return Integer.toString(value);
}
}
このことの配列をソートしたい。だから私は簡単な警官を作成しました:
private static final Comparator<Thing> reverse = new Comparator<Thing>() {
public int compare(Thing a, Thing b) {
return a.getValue() - b.getValue();
}
};
次に、 Arrays.sort
の2つの引数形式を使用します。
これは私のテストケースでは問題なく動作しますが、配列が奇妙で繰り返し可能な順序で終わる場合に、すべてがうまくいかないことがあります。 これはどのようにできますか?
解決
整数オーバーフロー&#8230;より正確には、アンダーフロー。
代わりに、明示的な比較を行います:
private static final Comparator<Thing> reverse = new Comparator<Thing>() {
public int compare(Thing a, Thing b) {
int av = a.getValue(), bv = b.getValue();
return (av == bv) ? 0 : ((av < bv) ? -1 : +1);
}
};
差が「ラップアラウンド」しないことが確実な場合は、減算を使用しても問題ありません。たとえば、問題の値が負でないように制限されている場合。
他のヒント
マイナスを使用して比較を作成することはできません。絶対差が Integer.MAX_VALUE
を超えるとオーバーフローします。
代わりに、このアルゴリズムを使用します:
int compareInts( int x, int y ) {
if ( x < y ) return -1;
if ( x > y ) return 1;
return 0;
}
このような目的のために、この関数をライブラリに入れたいです。
試用
System.out.println(Integer.MAX_Value - Integer.MIN_VALUE);
これは、MAX_VALUEとして正の数を返す必要があります&gt; MIN_VALUEであるが、代わりに-1を出力する
Javaプリミティブを比較するときは、それらを対応するオブジェクトに変換し、 compareTo()
メソッドに依存することをお勧めします。
この場合、次のことができます。
return Integer.valueOf(a.getValue()).compareTo(b.getValue())
疑わしい場合は、十分にテストされたライブラリを使用してください。
そこにはどのような数字を入れますか?数値が十分に大きい場合は、整数のMIN / MAX値を折り返し、混乱する可能性があります。
aの値が非常に負でbの値が非常に正の場合、答えは非常に間違っています。
IIRC、IntオーバーフローはJVMで静かにラップアラウンドします
-MarkusQ
所属していません StackOverflow