Гарантирован ли порядок возврата ключей и значений из объекта LinkedHashMap?

162

Я знаю, LinkedHashMapимеет предсказуемый порядок итераций (порядок вставки). Поддерживает ли Setвозвращенный LinkedHashMap.keySet()и Collectionвозвращаемый LinkedHashMap.values()также этот порядок?

user256239
источник
1
Поскольку все ответы касаются как проблемы, values()так и keySet()я, я расширил вопрос, чтобы включить это. Это означает, что больше вопросов могут быть закрыты как дубликаты этого.
Дункан Джонс

Ответы:

226

Интерфейс Map предоставляет три вида коллекций , которые позволяют просматривать содержимое карты в виде набора ключей, набора значений или набора отображений ключ-значение. Порядок на карте определяются как порядок , в котором итераторы на виде коллекционную карты Возвратятся их элементы. Некоторые реализации карт, такие как TreeMap класс, дают определенные гарантии относительно их порядка; другие, как HashMapкласс, не делают.

- Карта

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

- LinkedHashMap

Так что , да, keySet(), values(), и entrySet()(три мнения сбора упоминается) возвращаемые значения в порядке внутреннего связанного список использование. И да, JavaDoc для Mapи LinkedHashMapгарантировать его.

В этом смысл этого класса, в конце концов.

Powerlord
источник
8
итерация по карте также выполняется быстрее с использованием LinkedHashMap, чем HashMap.
Тьерри
2
values ​​() возвращает коллекцию. не список. как это держать это в порядке?
Dejell
7
@Dejel Collection- это просто базовый класс, для которого возвращается values ​​(). Реализация коллекции, которую он возвращает, все еще контролируется LinkedHashMap. В этом LinkedHashMapслучае он возвращает LinkedValuesэкземпляр, закрытый класс внутри LinkedHashMap.java.
Powerlord
2
Набор ключей LinkedHashMap в моем случае НЕ в порядке, представленном на карте. Очень озадачен этим.
Амальговинус
2
Благодарим Вас за ссылку на документацию (из Map), которая явно связывает порядок карты с итераторами в представлениях коллекции карты (и проясняете, каковы эти представления коллекции). Это был недостающий кусок для меня.
LarsH
11

Глядя на источник, похоже, что так и есть. keySet(), values()и entrySet()все используют один и тот же итератор записи внутри.

sblundy
источник
1
Было бы здорово иметь ссылку на репозитории, но я ленив :-) и, конечно, это не гарантия прямой совместимости.
Сиро Сантилли 郝海东 冠状 病 六四 事件 法轮功
6

Не путайте LinkedHashMap.keySet()и не LinkedHashMap.entrySet()возвращайте Set, и, следовательно, это не должно гарантировать заказ!

Setинтерфейс с HashSet, и TreeSetт.д. существа его реализации. HashSetРеализация Setинтерфейса не гарантирует порядок. Но TreeSetделает. Также LinkedHashSetделает.

Следовательно, зависит от того, как Setбыло реализовано, LinkedHashMapчтобы знать, будет ли возвращение ссылки Set гарантировать порядок или нет. Я прошел через исходный код LinkedHashMap, это выглядит так:

private final class KeySet extends AbstractSet<K> {...}
public abstract class AbstractSet<E> extends AbstractCollection<E> implements Set<E> {...}

Таким образом, LinkedHashMap / HashMap имеет собственную реализацию Setie KeySet. Таким образом, не путайте это с HashSet.

Кроме того, порядок поддерживается тем, как элементы вставляются в ведро. Посмотрите на addEntry(..)метод LinkedHashMapи сравните его с тем, HashMapкоторый подчеркивает основное различие между HashMapи LinkedHashMap.

anzaan
источник
4
Хотя этот ответ определенно представляет полезную информацию, он на самом деле не отвечает на вопрос. Это в основном говорит, что они могут иметь предсказуемый порядок итераций.
Tuupertunut
5

Вы можете предположить, что так. В Javadoc написано «предсказуемый порядок итераций», и единственные итераторы, доступные на карте, - это те, которые предназначены для keySet (), entrySet () и values ​​().

Таким образом, при отсутствии какой-либо дополнительной квалификации он явно предназначен для применения ко всем этим итераторам.

Маркиз Лорн
источник
0

AFAIK это не задокументировано, поэтому вы не можете «формально» предполагать это Однако маловероятно, что текущая реализация изменится.

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

Uri
источник
Вы имеете в виду entrySet () гарантирует порядок, а keySet () не гарантирует?
user256239
1
@kknight: я не уверен. Javadoc заявляет: «Этот связанный список определяет порядок итераций, который обычно является порядком, в котором ключи были вставлены в карту (порядок вставки).». Однако JavaDocs для JDK в целом очень неоднозначны.
Ури
5
Если даже entrySet () не гарантирует порядок итераций, то в чем разница между LinkedHashMap и HashMap? Как мы можем использовать предсказуемый порядок итераций в экземпляре LinkedHashMap?
user256239
1
Это, безусловно , является документально. Ответ совершенно неверный.
маркиз Лорн
-3

Глядя на интерфейс, он возвращает простой, Setа не SortedSet. Так что нет никаких гарантий.

Прежде чем принять на себя неявную гарантию, взглянув на реализацию (всегда плохая идея), также посмотрите на реализации во всех других реализациях Java :)

Вы могли бы лучше создать, например, TreeSet с keySet в конструкторе.

extraneon
источник
3
Если присмотреться к документации, то действительно есть гарантии. Как кто-то уже писал, в этом и заключается смысл этого занятия.
glglgl
-4

Я не думаю, что вы можете предполагать порядок keySet () и values ​​().

Я могу легко написать реализацию LinkedHashMap, которая возвращает вам неупорядоченные keySet () и values ​​(), если я придерживаюсь контракта этих двух методов, которые определены в Map и переопределены в HashMap.

Зоро
источник
6
Целью этого LinkedHashMapкласса является сохранение порядка элементов во время итерации карты, и это поведение хорошо определено. Если вы пишете подкласс без соблюдения спецификации базового класса, то вы делаете что-то очень неправильное.
Закинстер