Переопределение 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
?
2 ответа
Ваш хеш-код удовлетворяет свойству, что если два объекта равны, то их хеш-коды должны быть равны. Таким образом, это "достаточно хорошо". Однако довольно просто создать коллизии в хеш-кодах, которые ухудшат производительность структур данных, основанных на хешах.
Я бы реализовал это немного по-другому, хотя:
public int hashCode() {
return a * 13 + b.hashCode() * 23 + (c? 31: 7);
}
Вы должны проверить документацию для hashCode()
метод Object
, Он описывает то, что должен удовлетворить хеш-код.
Это полностью зависит от того, как будут выглядеть ваши данные. В большинстве случаев это был бы хороший подход. Если вы часто будете иметь b
заканчивая цифрой, вы получите дубликаты кодов для неравных объектов, как показывает ответ JacobM. Если вы заранее знаете, что b почти никогда не будет иметь числового значения в конце, то это разумный алгоритм хеширования.