web-dev-qa-db-ja.com

XORはJava hashCode()で頻繁に使用されますが、別のビット演算子はめったに使用されないのはなぜですか?

私はよく次のようなコードを見ます

int hashCode(){
  return a^b;
}

なぜXOR?

48
Andrei N

すべてのビット演算の中で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がたくさんある数値のいずれかに偏った数値が得られます。

88

XORには次の利点があります。

  • 計算の順序には依存しません。つまり、a ^ b = b ^ a
  • ビットを「無駄にする」ことはありません。コンポーネントの1つでビットを1つでも変更すると、最終的な値が変更されます。
  • 最も原始的なコンピュータでさえ、それは速く、単一のサイクルです。
  • 一様分布を維持します。組み合わせる2つのピースが均一に分散している場合、組み合わせも均一になります。言い換えれば、ダイジェストの範囲をより狭いバンドに縮小する傾向はありません。

詳細 ここ

19
dogbane

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暗号化で使用されるのですか?

4
Bhaskar

別のユースケースがあります:オブジェクトでは、(いくつかの)フィールドを順序に関係なく比較する必要があります。たとえば、ペアが必要な場合(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}
1
Sarge Borsch