我经常看到像
这样的代码int hashCode(){
return a^b;
}
为什么选择XOR?
答案 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具有以下优点:
更多信息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}