Java. Класс Object и его методы. Часть 2 — hashCode

Итак, в предыдущем посте мы ознакомились со списком методов класса Object и первым методом getClass() (ссылка). Далее идет метод hashCode и опять он помечен как native, но доступен для переопределения. Что важно, оно требует переопределения в классах, но обо всем по порядку. Метод возвращает хеш объекта в виде int. Давайте посмотрим, что это за число.

Дело в том, что это число генерируется (по умолчанию) рандомным способом (Park-Miller RNG). Но, это число постоянно для текущего объекта, что видно на примере цикличного вызова хешкода, так как записывается в заголовок объекта. 
Но для разных объектов оно будет разным.

Итак, зачем нужен метод hashCode? Когда мы сравниваем 2 примитива или объекта с помощью оператора ==, тогда сравниваются их hashCode. И если с примитивами все понятно (2 == 2 в любом случае), то с объектами дело обстоит иначе. Из-за случайной природы генерирования хешкода для объекта мы сталкиваемся со случаем, когда для двух разных объектов сгенерировались одинаковые хешкоды.


Я специально поставил в цикл 100 раз по миллиарду, чтобы наверняка наткнуться на такой кейс. Как видим вероятность мала, но она есть 7 к 100 млрд. И для того, чтобы избежать этой неприятности, в любом созданном классе нужно переопределить метод hashCode. Благо среда разработки предлагает шаблон.

Итого имеем метод, который учитывает все поля класса и генерит на их основе универсальный хешкод. В этом можно удостовериться повторно запустив метод с циклом в 100 миллиардов проверок. (Будьте осторожны, процессор может сильно нагреться)
На вопрос, откуда взялось число 31 как константа дает ответ книга Joshua Bloch Effective Java
The value 31 was chosen because it is an odd prime. If it were even and the multiplication overflowed, information would be lost, as multiplication by 2 is equivalent to shifting. The advantage of using a prime is less clear, but it is traditional. A nice property of 31 is that the multiplication can be replaced by a shift and a subtraction for better performance: 31 * i == (i << 5) - i. Modern VMs do this sort of optimization automatically.

Грубо говоря, 31 хорошее простое число, традиционно используемое для таких целей. Если использовать это число, то количество коллизий если и может быть, то будет минимальным (как видим, в нашем случае среди ста миллиардов повторов не произошла ни одна коллизия).

Итак, разобрались, почему нужно переопределять hashCode, теперь поговорим о методе equals, так как он тесно связан с получением хешкода. И это в следующем посте.

Запись опубликована в рубрике Программирование Java. Добавьте в закладки постоянную ссылку.

Один комментарий на «Java. Класс Object и его методы. Часть 2 — hashCode»

  1. dudeRazm говорит:

    Прямо на уровне объяснения!

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *