Переопределение 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 почти никогда не будет иметь числового значения в конце, то это разумный алгоритм хеширования.

Другие вопросы по тегам