Как 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 он основан на адресе памяти объекта.