Question

I have two related questions:

  1. the bitwise operator >>> means that we are shifting the binary number by those many places while filling 0 in the Most Significant Bit. But, then why does the following operation yields the same number: 5>>>32 yields 5 and -5>>>32 yields -5. Because if the above description is correct then both these operations would have yielded 0 as the final result.

  2. In continuation to above, As per Effective Java book, we should use (int) (f ^ (f >>> 32)) (in case the field is long) while calculating the hash code (if the field is long). Why do we do that and what's the explanation

Was it helpful?

Solution 2

Answer to your first question is here why is 1>>32 == 1?

The second question answer, in short, is that in such way the whole long value is used(not a part of it) and note that it is probably the fastest way to do this.

OTHER TIPS

5 can be represented as 0101 if you shift it by 1 bit i.e 5>>>1 this will result as 0010=2

If the promoted type of the left-hand operand is int, only the five lowest-order bits of the right-hand operand are used as the shift distance. It is as if the right-hand operand were subjected to a bitwise logical AND operator & (§15.22.1) with the mask value 0x1f. The shift distance actually used is therefore always in the range 0 to 31, inclusive.

When you shift an integer with the << or >> operator and the shift distance is greater than or equal to 32, you take the shift distance mod 32 (in other words, you mask off all but the low order 5 bits of the shift distance). This can be very counterintuitive. For example (i> >> 32) == i, for every integer i. You might expect it to shift the entire number off to the right, returning 0 for positive inputs and -1 for negative inputs, but it doesn't; it simply returns i, because (i << (32 & 0x1f)) == (i << 0) == i.

I know this question has been answered long back, but I tried an example to get more clarification and I guess it'll others too.

    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)));

This prints -

101111000001001111011001011110001000000000

1011110000

101111000001001111011001011110000011110000

1001111011001011110000011110000

As @avrilfanomar mentions, this XORs first 32 bits of long with the other 32 bits and unsigned right shift operator helps us in doing this. Since we want to use this long field while calculating the hashcode, directly casting the long to int would mean that long fields differing only in the upper 32 bits will contribute the same value to the hashcode. This potentially means that two objects differing only in this field will have same hashcode and it'll be stored in the same bucket (with say a list to resolve collision) and this impacts the performance of hash-based collections. Hence, this operation.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top