Как hashCode() реализован в Java

Как hashCode() реализовано?

Мое предположение заключается в том, что он использует местоположение памяти объекта как начальное число (семя), на котором он запускает хеш-функцию. Однако это не так.

Я также посмотрел на Хэш: как он работает внутри?, но он не отвечает на мой вопрос.

Да, я могу загрузить SDK, но прежде чем я это сделаю и посмотрю на код, возможно, кто-то еще уже знает об этом.

Спасибо:)

EDIT: Я знаю, что это должно быть переопределено и такое, поэтому, пожалуйста, постарайтесь остановиться на теме:)

Ответ 1

Конечно, это специфичная реализация, но, как правило, хэш-код для объекта будет вычисляться лениво и храниться в заголовке объекта. Нечетные вещи выполняются с заголовками, чтобы они были маленькими, позволяя создавать сложные алгоритмы блокировки.

В JVM OpenJDK/Oracle обычный метод вычисления исходного хэш-кода основан на адресе памяти во время первого запроса. Объекты перемещаются в памяти, поэтому использование адреса каждый раз не будет хорошим выбором. Хэш-код не является фактическим адресом, который обычно будет кратным восьми, что не очень удобно использовать прямо в хеш-таблице, особенно с мощностью двух размеров. Обратите внимание, что хэш-коды идентичности не уникальны.

У HotSpot есть параметры времени сборки, которые всегда используют нуль или используют защищенный генератор случайных чисел (SRNG) для целей тестирования.

Ответ 2

Нет, нет, нет. Все ответы в этой теме неправильны или хотя бы частично исправлены.

Во-первых: Object.hashCode() является нативным методом, поэтому его реализация зависит только от от JVM. Он может варьироваться между HotSpot и другими реализациями VM, такими как JRockit или IBM J9.

Если вы спрашиваете:

как реализована hashCode() в Java?

Тогда ответ: это зависит от того, какую виртуальную машину вы используете.

Предполагая, что вы используете JVM по умолчанию для Oracle, который является HotSpot, я могу сказать вам, что HotSpot имеет шесть реализаций hashCode(). Вы можете выбрать его с помощью флага -XX:hashCode=n, запускающего JVM через командную строку, где n может быть:

0 – Park-Miller RNG (default)
1 – f(address, global_statement)
2 – constant 1
3 – Serial counter
4 – Object address
5 – Thread-local Xorshift

Вышеуказанное копируется из этого сообщения.

И если вы копаете немного в исходном коде HotSpot, вы можете найти ниже фрагмент:

if (hashCode == 0) {
  value = os::random();
} else {
  ...

os::random() - это просто реализация алгоритма псевдо-случайного генератора Парка-Миллера.

Это все. Нет никакого понятия адреса памяти.. Хотя две другие реализации, 1 и 4, используют адрес памяти объекта, по умолчанию он не использует его.
Понятие о том, что Object.hashCode() основано на адресе объекта, в значительной степени является историческим артефактом - это уже не так.


Я знаю, что внутри Object#hashCode() JavaDoc мы можем читать:

(...) это обычно реализуется путем преобразования внутреннего адреса объекта в целое число, но этот способ реализации не требуется языком программирования Java ™.

Но это устарело и вводит в заблуждение.

Ответ 3

Реализация функции hashcode() изменяется от Object to Object. Если вы хотите знать, как определенный класс реализует hashcode(), вам придется искать его для этого класса.

Ответ 4

Метод hashCode, определенный классом Object, возвращает различные целые числа для разных объектов. Это может быть реализовано путем преобразования внутреннего адреса объекта в целое число (но этот стиль реализации не требуется стандартом). Он становится интересным с новыми классами, которые переопределяют hashCode для поддержки хэш-таблиц (equal и hashCode): http://www.javapractices.com/topic/TopicAction.do?Id=28

Ответ 5

Я предполагаю, что вы говорите о реализации Object hashCode, так как метод может и должен быть переопределен.

Это зависит от реализации. Для Sun JDK он основан на адресе памяти объекта.