Guavaのソースコードを閲覧しているときに、次のコード(hashCode
内部クラスのの実装の一部)に遭遇しましたCartesianSet
。
int adjust = size() - 1;
for (int i = 0; i < axes.size(); i++) {
adjust *= 31;
adjust = ~~adjust;
// in GWT, we have to deal with integer overflow carefully
}
int hash = 1;
for (Set<E> axis : axes) {
hash = 31 * hash + (size() / axis.size() * axis.hashCode());
hash = ~~hash;
}
hash += adjust;
return ~~hash;
両方adjust
とhash
しているint
の。私は、Java、について知っていることから、~
否定ビット単位手段、そうadjust = ~~adjust
とhash = ~~hash
変わらない変数を残す必要があります。小さなテストを実行します(もちろん、アサーションを有効にして)、
for (int i = Integer.MIN_VALUE; i < Integer.MAX_VALUE; i++) {
assert i == ~~i;
}
これを確認します。グアバの連中が彼らが何をしているか知っていると仮定すると、彼らがこれをする理由があるに違いない。問題は何ですか?
編集コメントで指摘されているように、上記のテストにはがi
等しい場合は含まれていませんInteger.MAX_VALUE
。以来i <= Integer.MAX_VALUE
、常に真実である、私たちは永遠にループするからそれを防ぐために、ループの外にそのような場合を確認する必要があります。ただし、行
assert Integer.MAX_VALUE == ~~Integer.MAX_VALUE;
コンパイラの警告「同一の式を比較しています」を生成します。
Integer.MAX_VALUE
。と対比-(-Integer.MIN_VALUE) != Integer.MIN_VALUE
。
-Integer.MIN_VALUE
にラップアラウンドするInteger.MIN_VALUE
ので、それを否定すると、単にInteger.MIN_VALUE
再び生成されます。
-x = (~x) + 1
ます。