Я задавался вопросом, как Java заказывает объекты в Map
(HashMap
или Hashtable
) когда они добавляются. Ключи заказаны хэш-кодом, ссылкой памяти или по приоритету выделения...?
Это - потому что я заметил тех же пар в Map
находятся не всегда в том же порядке
java.util.HashMap
неупорядочен; вы не можете и не должны предполагать ничего, кроме этого.
Этот класс не дает никаких гарантий относительно порядка отображения; в частности, это не гарантирует, что порядок останется постоянным с течением времени.
java.util.LinkedHashMap
использует порядок вставки.
Эта реализация отличается от
HashMap
тем, что поддерживает двусвязный список, проходящий через все его записи. Этот связанный список определяет порядок итераций, который обычно является порядком, в котором ключи были вставлены в карту (порядок вставки).
java.util.TreeMap
, SortedMap
, использует естественный или настраиваемый порядок ключей.
Карта сортируется в соответствии с естественным порядком ее ключей или с помощью
Компаратора
, предоставляемого во время создания карты, в зависимости от того, какой конструктор используется.
HashMap сохраняет значения, используя уникальное хеш-значение, сгенерированное с использованием части ключа. Это хеш-значение отображается на адрес, где оно будет храниться. Так обеспечивается доступ O (1).
LinkedHashmap, с другой стороны, сохраняет порядок, в котором вы добавили на карту.
Прежде всего: HashMap
конкретно не предоставляет стабильного и/или определенного упорядочивания. Поэтому все, что вы наблюдаете, является просто деталью реализации, и вы не должны зависеть от этого каким-либо образом.
Поскольку иногда полезно знать причину кажущегося случайным упорядочивания, вот основная идея:
У HashMap
есть несколько ведер (реализованных как массив), в которых хранятся записи.
Когда элемент добавляется в карту, он назначается в ведро на основе значения, полученного из его hashCode
и размера ведра HashMap
. (Обратите внимание, что возможно, что ведро уже занято, что называется коллизией. Это обрабатывается изящно и правильно, но я буду игнорировать эту обработку для описания, потому что это не меняет концепции).
Воспринимаемый порядок записей (например, возвращаемый итерацией по Map
) зависит от порядка записей в этих ведрах.
Всякий раз, когда размер перечитывается (потому что карта превысила порог полноты), количество ведер изменяется, что означает, что положение каждого элемента может измениться, поскольку положение ведра также зависит от количества ведер.
Карта
не является упорядоченной структурой данных - вы не должны полагаться на то, что записи в HashMap
находятся в определенном порядке. Некоторые реализации Map
, такие как LinkedHashMap
и TreeMap
, действительно гарантируют определенный порядок, а HashMap
- нет.
Если вы действительно хотите знать, что происходит внутри, поищите исходный код HashMap
- вы можете найти его в src.zip , который должен находиться в каталоге установки JDK.
A HashMap
имеет ряд «корзин», в которых он хранит свои записи. В каком сегменте хранится запись, определяется хэш-кодом ключа записи. Порядок, в котором вы видите записи в HashMap
, зависит от хэш-кодов ключей. Но не пишите программы, которые полагаются на то, что записи находятся в определенном порядке в HashMap
- реализация может измениться в будущей версии Java, и тогда ваша программа больше не будет работать.
HashMap
не выполняет сортировку. Для карты, которая сортирует по ключевым значениям, вы должны вместо этого использовать TreeMap
.
Из JavaDocs для TreeMap
:
Реализация интерфейса SortedMap на основе красно-черного дерева . Этот класс гарантирует, что карта будет располагаться в порядке возрастания ключей, отсортированном в соответствии с естественным порядком для класса ключа (см. Сопоставимый) или по компаратор , предоставленный во время создания, в зависимости от того, какой конструктор используется.
Из документации HashMap
:
Этот класс не дает никаких гарантий относительно порядка отображения; в частности, это не гарантирует, что порядок останется постоянным с течением времени.
В хеш-таблице нет определенного порядка. Ключи помещаются в слот на основе хэш-кода, но даже это не является тривиальным порядком хеш-кода.