为什么XOR经常用在java hashCode()中,但是另一个按位运算符很less被使用?

我经常看到类似的代码

int hashCode(){ return a^b; } 

为什么是异或?

在所有比特操作中,XOR具有最好的比特混洗属性。

这个真值表解释了为什么:

 AB AND 0 0 0 0 1 0 1 0 0 1 1 1 AB OR 0 0 0 0 1 1 1 0 1 1 1 1 AB XOR 0 0 0 0 1 1 1 0 1 1 1 0 

正如你所看到的AND和OR在混合位上做的不好。

OR将平均产生3/4个一位。 另一方面将产生平均3/4的空位。 只有XOR具有一位与零位的分布。 这使得散列码生成非常有价值。

请记住,对于散列码,您希望尽可能多地使用关键字的信息,并获得散列值的良好分布。 如果你使用AND或者OR,你会得到一些数字,这些数字有很多零的数字或者有很多数字的数字。

异或具有以下优点:

  • 它不依赖于计算的顺序,即a ^ b = b ^ a
  • 它不会“浪费”位。 如果你改变一个组件中的一个位,最终的值将会改变。
  • 即使是最原始的计算机上也是一个单一的循环。
  • 它保持均匀分布。 如果你组合的两块是均匀分布的,那么组合就是这样。 换句话说,它并不倾向于把摘要的范围缩小到一个更窄的范围。

更多信息在这里 。

异或opertpr是可逆的,即假设我有一个位串作为0 0 1并与另一个位串1 1 1异或,输出是

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

现在我可以agan异或第一个string的结果得到第二个string。 即

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

所以,这使得第二个string成为关键。 其他位操作符未find此行为

请参阅这个了解更多信息 – > 为什么在密码学上使用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} 
Interesting Posts