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
sです。私がJavaについて知っていることから、~
はビットごとの否定を意味するので、adjust = ~~adjust
とhash = ~~hash
は変数を変更しないでください。小さなテストを実行します(もちろん、アサーションを有効にして)。
for (int i = Integer.MIN_VALUE; i < Integer.MAX_VALUE; i++) {
assert i == ~~i;
}
これを確認します。グアバの人々が彼らが何をしているかを知っていると仮定すると、彼らがこれをする理由がなければなりません。質問は何ですか?
EDITコメントで指摘したように、上記のテストにはi
がInteger.MAX_VALUE
と等しい場合は含まれません。 i <= Integer.MAX_VALUE
は常にtrueであるため、そのケースをループ外でチェックして、永久にループしないようにする必要があります。ただし、行
assert Integer.MAX_VALUE == ~~Integer.MAX_VALUE;
コンパイラ警告「同一の式の比較」を生成します。
Javaでは、何も意味しません。
しかし、そのコメントは、この行はGWT専用であり、JavaをJavaScriptにコンパイルする方法だと述べています。
JavaScriptでは、整数はdouble-that-act-as-integersのようなものです。たとえば、最大値は2 ^ 53です。しかし、 ビットごとの演算子 は、32ビットであるかのように数値を処理します。これはまさにこのコードで必要なものです。つまり、~~hash
は、JavaScriptで「hash
を32ビット数として扱う」と言います。具体的には、下位32ビットを除くすべてを破棄します(ビット単位の~
演算子は下位32ビットのみを参照するため)。これは、Javaのオーバーフローの仕組みと同じです。
それがない場合、オブジェクトのハッシュコードは、Javaランドで評価されるかJavaScriptランドで評価されるかによって異なります(GWTコンパイルを介して)。