Страницы

Поиск по вопросам

суббота, 30 ноября 2019 г.

Использование чисел при переопределении метода hashCode

#java #hashcode


Да, в гугле можно найти статью 
Разбираемся с hashCode() и equals(), где вполне доступным языком описаны правила
переопределения hashCode() и equals(). В крайнем случае можно взять того же Блоха с
его Философией Java и посмотреть там эти правила. Речь не об этом. Правила мне понятны.

Непонятно вот что:

@Override
public int hashCode() {
    int hash = 37;
    hash = hash * 17 + str1.hashCode();
    hash = hash * 17 + str2.hashCode();
    hash = hash * 17 + num;                      
    return hash;
}


В разных примерах за основу берут какие-то числа. В данном примере взяты 37 и 17.
Таких примеров в Интернете масса, но в каждом из них числа разные. В одном примере
вообще встретилась такая конструкция:

@Override
public int hashCode() {
    int hash = new Random().nextInt(255);
    hash = hash * 255 + dozer.hashCode();
    hash = hash * 255 + tank.hashCode();              
    return hash;
}


Что окончательно сбило меня с толку. Как всё же правильно переопределять хеш-код? 

В связи с этим ряд вопросов:


Нужно ли вообще использовать какие-то числа?
Есть ли разница какое число выбирать? Или это некая "договорённость" внутри команды
при разработке продукта? 
Существуют ли ограничения на выбор стартового числа?
Почему каждый раз хеш нужно умножать сам на себя (прибавление хешей полей объекта
мне понятно)?

    


Ответы

Ответ 1



Почему используется 37 и 17 ? Как правило, в качестве начального значения выбирается простое число, это сделано для уменьшения вероятности возникновения коллизии. Смысл какое число выбирать, конечно, имеет. Если вы будете хранить ваши объекты в хэш таблице, то ее производительность прямо зависит от реализации hashCode() см. пункт 1 Для того, чтобы значения хэша были максимально отличны для объектов имеющих одинаковые значения полей. Этим мы добиваемся равномерного распредления ключей, в хэш таблице.

Ответ 2



Вот в этой статье упоминаются такие числа - Заметки о реализации hashCode() в Java. Совсем не обязательно использовать какие-то "магические" числа, скорее всего в примерах это сделано для уменьшения коллизий. Например, hashCode класса Integer просто возвращает число, которое было записано в переменную, т.е. внутри никакого умножения на какое-либо число нет.

Комментариев нет:

Отправить комментарий