Переопределение hashCode() - это достаточно хорошо?
Для класса, поля которого являются исключительно примитивными, например:
class Foo
{
int a;
String b;
boolean c;
long d;
boolean equals(Object o)
{
if (this == o) return true;
if (!(o instanceof Foo)) return false;
Foo other = (Foo) o;
return a == other.a && b.equals(other.b) && c == other.c && d = other.d;
}
}
Является ли это достаточно "хорошим" способом написать hashCode()
?
boolean hashCode()
{
return (b + a + c + d).hashCode();
}
То есть я создаю String
из тех же полей, которые использует equals()
, а затем просто используйте String#hashCode()
.
Изменить: Я обновил свой вопрос, включив в него поле long
. Как следует обрабатывать long
в hashCode()
? Просто позвольте этому переполнению int
?
Ответы
Ответ 1
Ваш хэш-код удовлетворяет этому свойству, что если два объекта равны, то их хэш-коды должны быть равны. Таким образом, это "достаточно хорошо". Однако довольно просто создать коллизии в хеш-кодах, что ухудшит производительность хэш-структуры данных.
Я бы выполнил его несколько иначе:
public int hashCode() {
return a * 13 + b.hashCode() * 23 + (c? 31: 7);
}
Вы должны проверить документацию для метода hashCode()
Object
. В нем описаны вещи, которые должен удовлетворять хэш-код.
Ответ 2
Все зависит от того, как будут выглядеть ваши данные. В большинстве случаев это было бы хорошим подходом. Если у вас часто заканчивается число b
с номером, то вы получите несколько повторяющихся кодов для неравных объектов, как показывает ответ JacobM. Если вы заранее знаете, что b в конце концов никогда не будет иметь числового значения в конце, то это разумный алгоритм хэширования.