按位运算符>>>在hashCode中

时间:2013-10-28 08:06:40

标签: java hashcode bitwise-operators gethashcode effective-java

我有两个相关的问题:

  1. 按位运算符>>>意味着我们正在将二进制数转移到那些多个位置,同时在最高位填充0。但是,为什么以下操作产生相同的数字:5>>> 32产生5和-5>>> 32产生-5。因为如果上面的描述是正确的,那么这两个操作都会产生0作为最终结果。

  2. 继续上面,根据Effective Java书,我们应该在计算哈希码时使用(int)(f ^(f>>>> 32))(如果字段很长) (如果字段很长)。为什么我们这样做以及解释是什么

3 个答案:

答案 0 :(得分:3)

5可以表示为0101如果您将其移位1位,5>>>1这将导致0010=2

  

如果左侧操作数的提升类型是int,则只有五个   右侧操作数的最低位用作移位   距离。好像右手操作数受到了a   按位逻辑AND运算符& (§15.22.1),掩码值为0x1f。   因此,实际使用的移位距离始终在0到0的范围内   31,包容性。

     

使用<<移位整数时或>>操作员和班次   距离大于或等于32,你采取移位距离   mod 32(换句话说,你屏蔽除了低位5位之外的所有   移动距离)。这可能非常违反直觉。例如(i>>>> 32)== i,对于每个整数i。您可能希望它将整个数字向右移动,对于正输入和-1返回0   对于负面投入,但它没有;它只是返回i,因为(i   << (32& 0x1f))==(i<< 0)== i。

答案 1 :(得分:2)

回答第一个问题是why is 1>>32 == 1?

第二个问题的答案,简而言之,就是以这种方式使用整个长值(而不是它的一部分),并注意到它可能是最快的方法。

答案 2 :(得分:2)

我知道这个问题早已得到回答,但我尝试了一个例子以获得更多澄清,我猜其他人也是如此。

    long x = 3231147483648l;
    System.out.println(Long.toBinaryString(x));
    System.out.println(Long.toBinaryString(x >>> 32));
    System.out.println(Long.toBinaryString(x ^ (x >>> 32)));
    System.out.println(Long.toBinaryString((int) x ^ (x >>> 32)));

打印 -

  

101111000001001111011001011110001000000000

     

1011110000

     

101111000001001111011001011110000011110000

     

1001111011001011110000011110000

正如@avrilfanomar所提到的,这个XOR前32位长与其他32位和无符号右移运算符帮助我们这样做。由于我们希望在计算哈希码时使用此长字段,因此直接将long强制转换为int将意味着只有高32位的long字段将为该字段提供相同的值。哈希码。这可能意味着仅在此字段中有两个不同的对象将具有相同的哈希码,并且它将存储在同一个存储桶中(例如用于解决冲突的列表),这会影响基于哈希的集合的性能。因此,这个操作。