Я задавался вопросом, мог ли кто-то объяснить подробно что
(int)(l ^ (l >>> 32));
делает в следующей реализации хэш-кода (сгенерированный затмением, но тем же как Эффективный Java):
private int i;
private char c;
private boolean b;
private short s;
private long l;
private double d;
private float f;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + i;
result = prime * result + s;
result = prime * result + (b ? 1231 : 1237);
result = prime * result + c;
long t = Double.doubleToLongBits(d);
result = prime * result + (int) (t ^ (t >>> 32));
result = prime * result + Float.floatToIntBits(f);
result = prime * result + (int) (l ^ (l >>> 32));
return result;
}
Спасибо!
По сути, он выполняет операцию XOR для верхних 32 бита длинного с нижними 32 бита. Вот расширенная версия:
// Unsigned shift by 32 bits, so top 32 bits of topBits will be 0,
// bottom 32 bits of topBits will be the top 32 bits of l
long topBits = l >>> 32;
// XOR topBits with l; the top 32 bits will effectively be left
// alone, but that doesn't matter because of the next step. The
// bottom 32 bits will be the XOR of the top and bottom 32 bits of l
long xor = l ^ topBits;
// Convert the long to an int - this basically ditches the top 32 bits
int hash = (int) xor;
Чтобы ответить на ваш комментарий: у вас есть длинное значение, которое должно быть преобразовано в int, чтобы быть частью хэша (результат должен быть только 32 бита). Как ты собираешься это сделать? Вы можете просто взять нижние 32 бита - но тогда это означает, что изменения в только верхних 32 бита будут проигнорированы, что не сделает его очень хорошим хешем. Таким образом, изменение одного бита ввода всегда приводит к изменению одного бита хэша. По общему признанию, вы все еще можете легко получить коллизии - измените оба бита 7 и 39, например, или любую другую пару битов на 32 позиции друг от друга - но это обязательно так, учитывая, что вы идете с 2 64 возможных значений до 2 32 .
Он берет 64-битное число, делит его пополам и сравнивает две половины вместе (по сути).
Берется (64-битное) long
l
, эксклюзивно-орбитально объединяет верхнюю и нижнюю половины (по 32 бита) в нижние 32 бита 64-битного результата, затем берет только нижние 32 бита с помощью (int)
приведения.