TGViewer
Java: fill the gaps Java: fill the gaps @java_fillthegaps · 12.3K subscribers
Post #556 15.5K
Как считается хэшкод по умолчанию?

На собеседованиях часто обсуждают методы equals и hashcode. За что отвечают, как соотносятся между собой, когда переопределять, а когда не стоит.

Если хочется посмотреть, как думает человек за пределами стандартного ответа, возможен такой диалог:

— Как считается хэшкод по умолчанию?
— Это адрес объекта в памяти
— А почему так?
— Адрес каждого объекта уникален, то что надо для хэшкода
— Сборщик мусора перемещает объекты внутри памяти. Как это влияет на значения хэшей?
— 😥


Тут можно предположить, что хэшкод считается один раз и приписывается к самому объекту. Это будет логичная мысль.

А вот вычисление хэша на основе адреса в памяти — популярный миф. В этом посте разберём, как на самом считается хэшкод под умолчанию.

В разных JVM реализации могут отличаться. Рассмотрим исходный код hashcode в OpenJDK. Там 6(!) стратегий вычисления хэшкода. Стратегия задаётся опциями VM:
-XX:+UnlockExperimentalVMOptions -XX:hashCode={число}

При первом вызове хэш сохраняется внутри объекта и не меняется. Теперь к стратегиям:

🔸-XX:hashCode=0

Случайное число по алгоритму Lehmer RNG. Генератор один на всех, поэтому работает медленно

🔸-XX:hashCode=2

Чемпион по скорости, всегда возвращает 1:
java.lang.Object@1

Используется как отправная точка для тестов остальных стратегий

🔸-XX:hashCode=3

Обычная возрастающая последовательность:
java.lang.Object@a4
java.lang.Object@a5
java.lang.Object@a6


🔸-XX:hashCode=4

Текущий адрес в памяти. Популярный, но неправильный ответ на собеседованиях. Отчасти в этом виновата спецификация: там адрес приводится как пример реализации. Работает быстро, но не даёт равномерного распределения и должного уровня уникальности

🔸-XX:hashCode=1

Адрес объекта в памяти и немного манипуляций с битами

🔸 Стратегия по умолчанию

Случайное число по алгоритму Xorshift RNG. Следующее значение вычисляется на основе предыдущего. Значения равномерно распределены. Работает быстро, тк у каждого потока свой генератор, и синхронизации между потоками нет

Рейтинг стратегий по скорости:
🏆 Вернуть единицу: 184 операций за микросекунду
🥈 Вариант по умолчанию: 176 оп/мск
🥉 Адрес в памяти-1: 160 оп/мск
▪️ Растущая последовательность: 14 оп/мск
▪️ Случайное число и глобальная переменная: 10 оп/мск

Интересно, что до java 8 самая медленная опция была вариантом по умолчанию.

Итого

✅ Реализация хэшкода зависит от JVM и VM-флажков
✅ В OpenJDK 6 стратегий вычисления хэшкода. По умолчанию используется генератор случайных чисел в рамках одного потока
✅ Расчёт на основе адреса памяти не очень хорош по итоговым характеристикам
✅ Общие переменные в методах снижают производительность при интенсивном использовании. Яркие примеры — стратегии хэшкода с общим генератором и последовательностью
  • 🔥 222
  • 👍 81
  • ❤ 28
  • 👎 4
More from @java_fillthegaps
  1. Apr 30, 2026Get Your Hands Dirty on Clean Architecture: отзыв на книгу Когда я подняла тему чистой арх…
  2. Apr 27, 2026​Clean Architecture: отзыв на книгу Наконец-то дочитала книгу Clean Architecture Роберта М…
  3. Mar 4, 2026Как переиспользовать контекст в интеграционных тестах Сегодня расскажу базовый минимум для…
  4. Mar 4, 2026Post #660
  5. Mar 4, 2026Тестовый контекст поднимается 2 минуты. У нас 4 класса с интеграционными тестами, их конфи…
  6. Feb 25, 2026Чистая архитектура. Главы 3-5 Продолжаем спидран по Clean Architecture Роберта Мартина. ⭐️…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →