что такое хэш код java

Хэш-код объекта, hashCode

Рассмотрим простой пример HashCodeTest.java, который в консоли будет печатать значение hashCode.

Значение hashCode программы можно увидеть в консоли.

По умолчанию, функция hashCode() для объекта возвращает номер ячейки памяти, где объект сохраняется. Поэтому, если изменение в код приложения не вносятся, то функция должна выдавать одно и то же значение. При незначительном изменении кода значение hashCode также изменится.

Функция сравнения объектов equals()

В родительском классе Object наряду с функцией hashCode() имеется еще и логическая функция equals(Object)/ Функция equals(Object) используется для проверки равенства двух объектов. Реализация данной функции по умолчанию просто проверяет по ссылкам два объекта на предмет их эквивалентности.

Рассмотрим пример сравнения двух однотипных объектов Test следующего вида :

Создадим 2 объекта типа Test с одинаковыми значениями и сравним объекты с использованием функции equals().

Результат выполнения программы будет выведен в консоль :

Не трудно было догадаться, что результат сравнения двух объектов вернет «false». На самом деле, это не совсем верно, поскольку объекты идентичны и в real time application метод должен вернуть true. Чтобы достигнуть этого корректного поведения, необходимо переопределить метод equals() объекта Test.

Вот теперь функция сравнения equals() возвращает значение «true». Достаточно ли этого? Попробуем добавить объекты в коллекцию HashSet и посмотрим, сколько объектов будет в коллекции? Для этого в в метод main примера EqualsExample добавим следующие строки :

Однако в коллекции у нас два объекта.

Поскольку Set содержит только уникальные объекты, то внутри HashSet должен быть только один экземпляр. Чтобы этого достичь, объекты должны возвращать одинаковый hashCode. То есть нам необходимо переопределить также функцию hashCode() вместе с equals().

Таким образом, переопределяя методы hashCode() и equals() мы можем корректно управлять нашими объектами, не допуская их дублирования.

Использование библиотеки commons-lang.jar для переопределения hashCode() и equals()

Процесс формирования методов hashCode() и equals() в IDE Eclipse автоматизирован. Для создания данных методов необходимо правой клавишей мыши вызвать контекстное меню класса (кликнуть на классе) и выбрать пункт меню Source (Class >> Source), в результате которого будет открыто следующее окно со списком меню для класса.

что такое хэш код java. hashcode generate. что такое хэш код java фото. что такое хэш код java-hashcode generate. картинка что такое хэш код java. картинка hashcode generate. Рассмотрим простой пример HashCodeTest.java, который в консоли будет печатать значение hashCode.

Выбираем пункт меню «Generate hachCode() and equals()» и в класс будут добавлены соответствующие методы.

Библиотека Apache Commons включает два вспомогательных класса HashCodeBuilder и EqualsBuilder для вызова методов hashCode() и equals(). Чтобы включить их в класс необходимо внести следующие изменения.

Примечание : желательно в методах hashCode() и equals() не использовать ссылки на поля, заменяйте их геттерами. Это связано с тем, что в некоторых технологиях java поля загружаются при помощи отложенной загрузки (lazy load) и не доступны, пока не вызваны их геттеры.

Скачать пример

Исходный код рассмотренного примера в виде проекта Eclipse можно скачать здесь (263 Kб).

Источник

Заметки о реализации hashCode() в Java

Часто на собеседованиях приходится спрашивать про функцию hashCode().
Я не буду здесь перечислять все свойства этой функции и ее связь с другой, не менее важной функцией equals(). Данная информация есть во всех учебниках по Java и я не вижу смысла ее здесь повторять. Мне бы хотелось остановиться лишь на одном свойстве: hashCode должен быть равномерно распределен на области значений функции. Я задумался: “А чем гарантировано равномерное распределение?”

Забегая вперед, скажу, что я пришел к довольно интересным выводам. Мне бы хотелось, чтобы меня поправили, если я где-то ошибся в рассуждениях.

Спросим у Гуру

Вначале я решил обратиться к Java документации на Object.hashCode(). Как каждый может убедиться, там нет информации, которая нас интересует. После этого я пошел к Гуру. Брюс Эккель написал 5 страниц, кивнул на Блоха (точнее списал у него), привел пример со строками, а в конце посоветовал использовать “полезные библиотеки”. Джошуа Блох поступил лучше: он предложил алгоритм вычисления, высказался о пользе простых чисел и… тоже привел пример. Я не могу не удержаться от цитирования:

The multiplier 37 was chosen because it is an odd prime. … The advantages of using a prime number are less clear, but it is traditional to use primes for this purpose.

Никто из авторов не удосужился провести анализ приведенного алгоритма и доказать его корректность.

Алгоритм (в вольном пересказе)

1) Взять число, отличное от нуля, к примеру 17. Для удобства, назовем его p. Присвоить переменной result это начальное значение (result = p).
2) Для каждого поля вычислить hashCode c по некоторым правилам. Эти правила, нас сейчас не очень интересуют, они не влияют на результат. Для простоты будем работать с целыми числами (int) и будем принимать hashCode равным самому значению числа…
3) Скомбинировать result и полученный hashCode с: result = result * q + c, где q = 37, потому что, как мы помним, оно нечетное и простое.
4) Вернуть result.

Анализ алгоритма

Чтобы быть более конкретным, я стану рассматривать точки с целочисленными координатами (x, y) на плоскости в двухмерном пространстве, при условии, что x>= 0, y>=0.

Запишем hash функцию для точки P1 (x1, y1):

q(x1-x2) + y1 — y2 = 0 (Обратите внимание, что множитель, содержащий p пропал после вычитания)

(x1 — x2) / (y2-y1) = q (понятно, что знаменатель должен быть отличен от нуля)

Если подобрать такие значения x1, x2, y1, y2, что выполнится полученное равенство, то эти координаты будут соответствовать значениям аргумента hash функции, при которой возникнет коллизия.

Можно предложить такой вариант:

То есть точки P(38, 1) и P(1, 2) имеют одинаковый hashCode… Я думал, что имея 4 миллиарда возможных значений для hash кода, можно было бы избежать коллизий хотя бы в квадрате 100×100!

Теперь рассмотрим случай n переменных, независимо изменяющихся от 0 до некоторого M. Хотелось бы найти максимальное значение M, такое, что хорошо написанная функция hashCode не имела бы коллизий на промежутке от 0 до M по всем n переменным. После недолгих раздумий, получаем значение для M:
что такое хэш код java. image loader. что такое хэш код java фото. что такое хэш код java-image loader. картинка что такое хэш код java. картинка image loader. Рассмотрим простой пример HashCodeTest.java, который в консоли будет печатать значение hashCode.
Для случая точек на плоскости M принимает значение 65536.

Похоже, что формула, приведенная Блохом, будет давать приемлемое распределение hash кодов для случая 8 и более переменных.

Рассмотрим теперь точки в трехмерном пространстве. Напишем небольшую программу, которая в тройном цикле перебирает точки от 0 до 100 (всего миллион точек) и считает количество коллизий. Код этой программы элементарный, поэтому не буду его здесь приводить. Интересен результат: я получил 901692 коллизий! То есть чуть более, чем 90%. Получается, что Блох, под видом hash функции, предложил функцию для получения коллизий?

Хороший hashCode для случая двух переменных

p*(x1-x2) + q(y1-y2) = 0
или
(x1-x2)/(y2-y1)=q/p (при условии, что знаменатель не равен нулю)

Выводы

Как писал Дональд Кнут в главе про генератор псевдослучайных последовательностей, если алгоритм выглядит сложно и запутанно, это еще не означает, что он работает правильно (недословное изложение).

Те кто используют реализацию hash функции от Джошуа Блоха, но имеют большое количество хешируемых переменных, могут спать спокойно. Так же могут не волноваться те, у кого различного рода Hash-коллекции не являются узким местом в производительности.

Если же вы бьетесь за производительность своего кода, учитываете все возможные мелочи, то вам, пожалуй, следует взглянуть на свои реализации hashCode() свежим взглядом. Учитывая, что хешируемые значения, могут быть не равномерно распределены для вашей конкретной бизнес области, вы сможете написать hash функцию с лучшим распределением hash кодов, чем любой сгенерированный вариант. Переписав hashCode(), вам, возможно, следует взглянуть на equals(): может быть вы сможете меньшим числом проверок вернуть значение false.

Спасибо тем, кто дочитал до конца.

Литература:
Bruce Eckel “Thinking in Java Third Edition”
Joshua Bloch “Effective Java: Programming Language Guide”

Источник

Как работает hashCode() по умолчанию?

что такое хэш код java. image loader. что такое хэш код java фото. что такое хэш код java-image loader. картинка что такое хэш код java. картинка image loader. Рассмотрим простой пример HashCodeTest.java, который в консоли будет печатать значение hashCode.

Тривиальная загадка

После корректирования toString() наш кастомный hashCode() перестал вызываться. Мы пропустили тест.

Чем является реализация по умолчанию hashCode()?

Здравый смысл подсказывает, что идентификационный хеш использует целочисленное представление адреса памяти. Об этом свидетельствует документация J2SE на Object.hashCode():

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

Однако с этим связаны проблемы, поскольку контракт метода (method contract) требует:

При применении к одному и тому же объекту более одного раза в ходе выполнения Java-приложения метод hashCode должен в обязательном порядке возвращать одно и то же целочисленное значение.

Учитывая, что JVM будет перемещать объекты (например, при сборке мусора в ходе продвижения или уплотнения), после вычисления идентификационного хеша объекта мы должны сделать так, чтобы он как-то отслеживал местоположение самого объекта.

Например, можно взять текущую позицию объекта в памяти при первом вызове hashCode() и сохранить её где-нибудь, например в заголовке объекта. Тогда при перемещении объекта в другое место с ним переедет и исходный хеш. Недостаток способа: два объекта могут иметь одинаковый хеш, но это разрешено спецификацией.

Лучшим подтверждением будет посмотреть в исходный код. К сожалению, дефолтная java.lang.Object::hashCode() является нативной функцией:

Настоящий hashCode()

Обратите внимание, что идентификационная реализация hashCode() зависит от JVM. Я буду рассматривать только исходный код OpenJDK, помните об этом при каждом дальнейшем упоминании JVM. Все ссылки относятся к набору изменений 5934:87ee5ee27509 дерева Hotspot, и полагаю, что большинство из них применимы и к Oracle JVM, но в других машинах есть свои нюансы.

Можно наивно ожидать, что ObjectSynchronizer::FastHashCode() делает что-то вроде:

Но оказывается, что там функция на сотню строк. А это куда сложнее. По крайней мере, мы можем отметить пару блоков «если-не-существует-то-генерировать»:

Реальное генерирование идентификационного хеша

0. Случайно сгенерированное число.
1. Функция адреса объекта в памяти.
2. Жёстко запрограммированное значение 1 (используется при тестировании на чувствительность (sensitivity testing)).
3. Последовательность.
4. Адрес объекта в памяти, приведённый к целочисленному значению.
5. Состояние потока, объединённое с xorshift (https://en.wikipedia.org/wiki/Xorshift)

Какой метод используется по умолчанию? Согласно globals.hpp, в OpenJDK 8 это метод 5:

Так что, если я не ошибаюсь, как минимум с шестой версии реализация по умолчанию hashCode в OpenJDK не имеет ничего общего с адресом памяти.

Заголовки объектов и синхронизация

Вернёмся немного и рассмотрим пару пропущенных моментов. Во-первых, функция ObjectSynchronizer::FastHashCode() выглядит слишком сложной, в ней используется больше 100 строк кода для выполнения того, что мы считали тривиальной операцией «получить-или-сгенерировать». Во-вторых, что это вообще такое – monitor – и почему у него есть заголовки нашего объекта?

Структура слова mark — хорошее место для начала изысканий. В OpenJDK она выглядит так:

Для 32 и 64 битов формат несколько различается. Во втором случае могут быть два варианта, в зависимости от того, включены ли указатели сжатых объектов (Compressed Object Pointers). В Oracle и OpenJDK 8 по умолчанию они включены.

Таким образом, заголовки объектов могут относиться к свободному блоку или к реальному объекту, так что возможны несколько разных состояний. В простейшем случае («нормальный объект») идентификационный хеш сохраняется напрямую в младшие биты заголовка.

Попробуем ответить на все эти вопросы.

Привязанная блокировка (biased locking)

Привязанные объекты — это результат привязанной блокировки. Это запатентованный механизм, по умолчанию используемый начиная с HotSpot 6. Он пытается снизить стоимость блокирования объектов. Подобные операции дороги, поскольку ради безопасной обработки запросов блокировки/разблокировки объекта от разных потоков их реализации часто опираются на атомарные процессорные инструкции (сравнение с обменом). Но подмечено, что во многих реализациях большинство объектов когда-либо блокируются лишь одним потоком, так что использование атомарных операций зачастую расточительно. Чтобы этого избежать, JVM’ы с привязанной блокировкой позволяют потокам попытаться самостоятельно «привязать» объект. Когда потоку это удаётся, он может блокировать/разблокировать объект без использования атомарных инструкций. А раз у нас нет потоков, борющихся за один и тот же объект, то мы получаем прирост производительности.

Погодите. Здесь просто отменяются привязка и привязанная блокировка объекта (метод false означает «не пытайся снова привязать»). Несколькими строками ниже это остаётся действительно неизменным:

Если я прочитал правильно, то простой запрос идентификационного хеша объекта отключает привязанную блокировку, что предотвратит любые попытки заблокировать объект для использования дорогих атомарных инструкций.

Почему сохранение состояния привязанной блокировки конфликтует с сохранением идентификационного хеша?

Для ответа на этот вопрос мы должны понять, где может находиться слово mark (содержащее идентификационный хеш) в зависимости от состояния блокировки объекта. Ниже показаны возможные переходы:

что такое хэш код java. image loader. что такое хэш код java фото. что такое хэш код java-image loader. картинка что такое хэш код java. картинка image loader. Рассмотрим простой пример HashCodeTest.java, который в консоли будет печатать значение hashCode.

Моё (возможно, ошибочное) мнение таково.

Для четырёх состояний в верхней части схемы OpenJDK сможет использовать представления thin-блокировок. В простейшем случае (без блокировок) это означает хранение идентификационного хеша и других данных прямо в пространстве слова mark в объекте:

В более сложных случаях это пространство используется для хранения указателя на «запись о блокировке». Тогда слово mark будет «перемещено» в другое место.

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

Нашим нуждам удовлетворяет структура ObjectMonitor, которая на схеме называется «тяжёлый монитор». Оставшееся в заголовке объекта значение указывает не на «перемещённое слово mark», а на реальный объект (монитор). Теперь для доступа к идентификационному хешу требуется «получить монитор» (inflating the monitor): сделать указатель на объект и считывать/изменять в зависимости от поля, содержащего перемещённое слово mark. Это дороже и требует координации.

В строках с L640 по L680 выполняется поиск заголовка и проверка на наличие закешированного идентификационного хеша. Я считаю, что это быстрый способ проверки случаев, когда нам не нужно получить монитор.

Начиная с L682 придётся стиснуть зубы:

Это даёт разумное объяснение, почему вызов hashCode() применительно к объекту класса, который не переопределяет реализацию по умолчанию, делает объекты недоступными для привязанной блокировки:

Промежуточные итоги

Бенчмарки

Для проверки своих умозаключений я написал простой тест JMH.

Бенчмарк (исходник) делает нечто вроде этого:

Кастомный хеш в четыре раза ускоряет цикл блокировки/разблокировки по сравнению с идентификационным хешем (который отключает привязанную блокировку). Когда за блокировку конкурируют два потока, привязанная блокировка отключается в любом случае, так что между двумя методам хеширования не наблюдается значимой разницы.

Метод хеширования больше не влияет на результат, и withoutIdHash теряет своё преимущество.

Все бенчмарки прогонялись на Intel Core i5 2,7 ГГц.

Ссылки

Всё, что не является дикими спекуляциями и моими слабыми рассуждениями в попытке осмыслить исходные коды JVM, собрано из разных источников. Основные из них:

Источник

Внутренняя работа HashMap в Java

В этой статье мы увидим, как изнутри работают методы get и put в коллекции HashMap. Какие операции выполняются. Как происходит хеширование. Как значение извлекается по ключу. Как хранятся пары ключ-значение.

Как и в предыдущей статье, HashMap содержит массив Node и Node может представлять класс, содержащий следующие объекты:

Теперь мы увидим, как все это работает. Для начала мы рассмотрим процесс хеширования.

Хэширование

Здесь я использую свой собственный класс Key и таким образом могу переопределить метод hashCode() для демонстрации различных сценариев. Мой класс Key:

Здесь переопределенный метод hashCode() возвращает ASCII код первого символа строки. Таким образом, если первые символы строки одинаковые, то и хэш коды будут одинаковыми. Не стоит использовать подобную логику в своих программах.

Этот код создан исключительно для демонстрации. Поскольку HashCode допускает ключ типа null, хэш код null всегда будет равен 0.

Метод hashCode()

Метод equals()

Метод equals используется для проверки двух объектов на равенство. Метод реализованн в классе Object. Вы можете переопределить его в своем собственном классе. В классе HashMap метод equals() используется для проверки равенства ключей. В случае, если ключи равны, метод equals() возвращает true, иначе false.

Корзины (Buckets)

Вычисление индекса в HashMap

Хэш код ключа может быть достаточно большим для создания массива. Сгенерированный хэш код может быть в диапазоне целочисленного типа и если мы создадим массив такого размера, то легко получим исключение outOfMemoryException. Потому мы генерируем индекс для минимизации размера массива. По сути для вычисления индекса выполняется следующая операция:

где n равна числу bucket или значению длины массива. В нашем примере я рассматриваю n, как значение по умолчанию равное 16.

HashMap:
что такое хэш код java. . что такое хэш код java фото. что такое хэш код java-. картинка что такое хэш код java. картинка . Рассмотрим простой пример HashCodeTest.java, который в консоли будет печатать значение hashCode.

Вычислить значение ключа <"vishal">. Оно будет сгенерированно, как 118.

Создать объект node.

Поместить объект в позицию с индексом 6, если место свободно.

Теперь HashMap выглядит примерно так:

что такое хэш код java. es4j78e 05gpk3babndygunccgq. что такое хэш код java фото. что такое хэш код java-es4j78e 05gpk3babndygunccgq. картинка что такое хэш код java. картинка es4j78e 05gpk3babndygunccgq. Рассмотрим простой пример HashCodeTest.java, который в консоли будет печатать значение hashCode.

Вычислить значение ключа <"sachin">. Оно будет сгенерированно, как 115.

Создать объект node.

Поместить объект в позицию с индексом 3, если место свободно.

Теперь HashMap выглядит примерно так:

что такое хэш код java. . что такое хэш код java фото. что такое хэш код java-. картинка что такое хэш код java. картинка . Рассмотрим простой пример HashCodeTest.java, который в консоли будет печатать значение hashCode.

Вычислить значение ключа <"vaibhav">. Оно будет сгенерированно, как 118.

Создать объект node.

Поместить объект в позицию с индексом 6, если место свободно.

В данном случае в позиции с индексом 6 уже существует другой объект, этот случай называется коллизией.

В таком случае проверям с помощью методов hashCode() и equals(), что оба ключа одинаковы.

Если ключи одинаковы, заменить текущее значение новым.

Иначе связать новый и старый объекты с помощью структуры данных «связанный список», указав ссылку на следующий объект в текущем и сохранить оба под индексом 6.

Теперь HashMap выглядит примерно так:

что такое хэш код java. . что такое хэш код java фото. что такое хэш код java-. картинка что такое хэш код java. картинка . Рассмотрим простой пример HashCodeTest.java, который в консоли будет печатать значение hashCode.

[примечание от автора перевода] Изображение взято из оригинальной статьи и изначально содержит ошибку. Ссылка на следующий объект в объекте vishal с индексом 6 не равна null, в ней содержится указатель на объект vaibhav.

Вычислить хэш код объекта <“sachin”>. Он был сгенерирован, как 115.

В нашем случае элемент найден и возвращаемое значение равно 30.

Вычислить хэш код объекта <"vaibhav">. Он был сгенерирован, как 118.

В данном случае он не найден и следующий объект node не равен null.

Если следующий объект node равен null, возвращаем null.

Если следующий объект node не равен null, переходим к нему и повторяем первые три шага до тех пор, пока элемент не будет найден или следующий объект node не будет равен null.

Изменения в Java 8

Для исправления этой проблемы в Java 8 после достижения определенного порога вместо связанных списков используются сбалансированные деревья. Это означает, что HashMap в начале сохраняет объекты в связанном списке, но после того, как колличество элементов в хэше достигает определенного порога происходит переход к сбалансированным деревьям. Что улучшает производительность в худшем случае с O(n) до O(log n).

Источник

Руководство по хэш-коду () на Java

Узнайте, как работает хэш-код и как его правильно реализовать.

1. Обзор

Хэшинг является фундаментальной концепцией информатики.

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

Дальнейшее чтение:

Java равно () и хэш-код () Контракты

Создание равных () и хэш-кода () с Eclipse

Введение в проект Ломбок

2. Использование хэш-кода () в структурах данных

Простейшие операции по сборам могут быть неэффективными в определенных ситуациях.

Например, это вызывает линейный поиск, который является крайне неэффективным для списков огромных размеров:

Java предоставляет ряд структур данных для решения этой проблемы в частности – например, несколько Карта реализации интерфейса хэш-таблицы.

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

3. Понимание того, как работает хэш-код ()

Проще говоря, хэш-код () возвращает значение integer, генерируемое алгоритмом хэширования.

Объекты, которые равны (в соответствии с их равными () ) должны вернуть тот же хэш-код. Для различных объектов не требуется возвращать различные хэш-коды.

Генеральный контракт хэш-код () Государств:

“Насколько это разумно практично, хэш-код () метод, определяемый классом Объект возвращает различные интеграторы для отдельных объектов. (Обычно это реализуется путем преобразования внутреннего адреса объекта в интегратор, но этот метод реализации не требуется языком программирования JavaTM.)»

4. Наивный хэш-код () Реализация

Это на самом деле довольно просто иметь наивный хэш-код () полностью придерживается вышеупомянутого контракта.

Чтобы продемонстрировать это, мы собираемся определить образец Пользователь класс, переопределяет реализацию метода по умолчанию:

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

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

В этом контексте поиск хэш-таблицы выполняется линейно и не дает нам реального преимущества – подробнее об этом в разделе 7.

5. Улучшение хэш-кода () Реализация

Давайте немного улучшить текущее хэш-код () реализации путем включения всех областей Пользователь класс, чтобы он может дать различные результаты для неравных объектов:

В общих чертах можно сказать, что это разумный хэш-код () реализации, до тех пор, как мы равны () реализации в соответствии с ним.

6. Стандартный хэш-код () Реализации

Чем лучше алгоритм хэширования, который мы используем для вычисления хэш-кодов, тем лучше будет производительность хэш-таблиц.

Давайте посмотрим на “стандартную” реализацию, которая использует два основных числа, чтобы добавить еще больше уникальности в вычисленные хэш-коды:

Хотя очень важно понимать роли, которые хэш-код () и равны () методы игры, мы не должны осуществлять их с нуля каждый раз, так как большинство IDEs может генерировать пользовательские хэш-код () и равны () реализации и с Java 7, мы получили Объекты.хэш () утилита для удобного хэширования:

IntelliJ IDEA генерирует следующую реализацию:

И Затмение производит этот:

Теперь достаточно аннотировать Пользователь класс с @EqualsAndHashCode :

Точно так же, если мы хотим Апач Викисклад Ланг HashCodeBuilder класс для создания хэш-код () реализации для нас, общий ланг Зависимость Maven должна быть включена в файл pom:

И хэш-код () могут быть реализованы так:

Что можно заметить здесь, что все эти реализации использовать номер 31 в той или иной форме – это потому, что 31 имеет хорошее свойство – его умножение может быть заменено немного сдвиг, который быстрее, чем стандартное умножение:

7. Обработка хэш-столкновений

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

“Когда два или более объектов указывают на одно и то же ведро, они просто хранятся в связанном списке. В этом случае таблица хэша является массивом связанных списков, и каждый объект с одним и тем же хэшом прибвётся к связанному списку индекса ведра в массиве.

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

8. Создание тривиального приложения

Проверить функциональность стандартного хэш-код () реализации, давайте создадим простое java-приложение, которое добавляет некоторые Пользователь объекты для HashMap и использует SLF4J для регистрации сообщения на консоли каждый раз, когда метод называется.

Вот точка входа образца приложения:

И это хэш-код () реализация:

Единственная деталь, которую стоит подчеркнуть здесь, состоит в том, что каждый раз объект хранится на хэш-карте и проверяется с содержитКей () метод, хэш-код () вызывается и вычисляемый хэш-код распечатан на консоли:

9. Заключение

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

Источник

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

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