compareTo
メソッドのJava.lang.Integer
の実装は次のようになることがわかりました。
public int compareTo(Integer anotherInteger) {
int thisVal = this.value;
int anotherVal = anotherInteger.value;
return (thisVal<anotherVal ? -1 : (thisVal==anotherVal ? 0 : 1));
}
問題は、減算ではなく比較を使用する理由です。
return thisVal - anotherVal;
これは整数オーバーフローが原因です。 thisVal
が非常に大きく、anotherVal
が負の場合、前者から後者を引くと、負の範囲にオーバーフローする可能性があるthisVal
より大きい結果が得られます。
2つの数値を比較するための減算「トリック」が壊れています!!!
int a = -2000000000;
int b = 2000000000;
System.out.println(a - b);
// prints "294967296"
ここに、 a < b
、まだa - b
は正です。
このイディオムは使用しないでください。動かない。
さらに、それが機能しても、[〜#〜] [〜#〜]は大幅な改善を提供しませんパフォーマンス、そして実際には読みやすさが犠牲になる場合があります。
このパズルにはいくつかの教訓があります。最も具体的なものは次のとおりです:値の差が決して大きくならないことが確実でない限り、減算ベースのコンパレータを使用しないでください
Integer.MAX_VALUE
。より一般的には、int
オーバーフローに注意してください。別の教訓は、「賢い」コードを避けるべきだということです。明確で正しいコードを書くように努め、必要でない限り最適化しないでください。
簡単に言えば、int
型は2つの任意のint
値の差を格納するのに十分な大きさではありません。たとえば、15億から-15億の差は30億ですが、int
は21億を超える値を保持できません。
おそらくそれはオーバーフロー/アンダーフローを回避することです。
オーバーフローに加えて、減算同じ結果が得られないのバージョンに注意してください。
オーバーフローがないことがわかっている場合は、次のようなものを使用できます。
public int compareTo(Integer anotherInteger) {
return sign(this.value - anotherInteger.valuel);
}