为什么XOR经常在java hashCode()中使用,但很少使用其他按位运算符?

时间:2010-02-25 13:21:17

标签: hash hashcode xor

我经常看到像

这样的代码
int hashCode(){
  return a^b;
}

为什么选择XOR?

4 个答案:

答案 0 :(得分:87)

在所有位操作中,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在混合位方面做得很差。

OR平均会产生3/4的一位。另一方面,AND将产生平均3/4的空位。只有XOR具有偶数一位与空位分布。这使得它对于哈希码生成非常有价值。

请记住,对于哈希代码,您希望尽可能多地使用密钥信息并获得良好的哈希值分布。如果您使用AND或OR,您将获得偏向于具有大量零或具有大量数字的数字的数字。

答案 1 :(得分:19)

XOR具有以下优点:

  • 它不依赖于计算的顺序,即a ^ b = b ^ a
  • 它不会“浪费”比特。如果您在其中一个组件中更改了一位,则最终值将会更改。
  • 即便是最原始的计算机,它也很快,一个循环。
  • 保持均匀分布。如果你组合的两个部分是均匀分布的,那么组合就是这样。换句话说,它不会将摘要的范围缩小到更窄的范围。

更多信息here

答案 2 :(得分:4)

XOR运算符是可逆的,即假设我有一个位串0 0 1,并且我用另一个位串1 1 1对它进行异或,输出为

0 xor 1 = 1
0     1 = 1
1     1 = 0

现在我可以再次使用结果xor第一个字符串来获取第二个字符串。即。

0   1 = 1
0   1 = 1
1   0 = 1

因此,这使得第二个字符串成为关键。其他位运算符

找不到此行为

请参阅此内容以获取更多信息 - > Why is XOR used on Cryptography?

答案 3 :(得分:1)

还有另一个用例:对象,其中(某些)字段必须进行比较而不考虑其顺序。例如,如果您希望一对(a, b)始终等于(b, a)对 XOR具有a ^ b = b ^ a的属性,因此在这种情况下它可以用于散列函数。

示例:(完整代码here

定义:

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}