私はよく次のようなコードを見ます
int hashCode(){
return a^b;
}
なぜXOR?
すべてのビット演算の中でXORは最高のビットシャッフル特性を持っています。
この真理値表はその理由を説明しています。
A B AND
0 0 0
0 1 0
1 0 0
1 1 1
A B OR
0 0 0
0 1 1
1 0 1
1 1 1
A B XOR
0 0 0
0 1 1
1 0 1
1 1 0
ANDとOR)でわかるように、ビットの混合はうまくいきません。
または、平均して3/4の1ビットを生成します。一方、平均で3/4のヌルビットが生成されます。 XORのみが、1ビットとnullビットの分布が均等であるため、ハッシュコード生成に非常に役立ちます。
ハッシュコードの場合、キーの情報をできるだけ多く使用し、ハッシュ値を適切に分散させたいことを忘れないでください。 ANDまたはORを使用すると、ゼロがたくさんある数値または1がたくさんある数値のいずれかに偏った数値が得られます。
XORには次の利点があります。
詳細 ここ 。
XOR演算子は可逆的です。つまり、ビット文字列が0 0 1
であり、I XOR別のビット文字列1 1 1
である場合、出力は次のようになります。
0 xor 1 = 1
0 1 = 1
1 1 = 0
これで、1番目の文字列をxorして結果を取得し、2番目の文字列を取得できます。つまり.
0 1 = 1
0 1 = 1
1 0 = 1
つまり、2番目の文字列がキーになります。この動作は他のビット演算子では見つかりません
詳細については、こちらをご覧ください-> なぜXOR暗号化で使用されるのですか?
別のユースケースがあります:オブジェクトでは、(いくつかの)フィールドを順序に関係なく比較する必要があります。たとえば、ペアが必要な場合(a, b)
常にペアに等しい(b, a)
。
XORにはa ^ b
= b ^ a
なので、このような場合にハッシュ関数で使用できます。
例:(完全なコード ここ )
定義:
final class Connection {
public final int A;
public final int B;
// some code omitted
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Connection that = (Connection) o;
return (A == that.A && B == that.B || A == that.B && B == that.A);
}
@Override
public int hashCode() {
return A ^ B;
}
// some code omitted
}
使用法:
HashSet<Connection> s = new HashSet<>();
s.add(new Connection(1, 3));
s.add(new Connection(2, 3));
s.add(new Connection(3, 2));
s.add(new Connection(1, 3));
s.add(new Connection(2, 1));
s.remove(new Connection(1, 2));
for (Connection x : s) {
System.out.println(x);
}
// output:
// Connection{A=2, B=3}
// Connection{A=1, B=3}