Чи гарантується порядок повернення ключів та значень об’єкта LinkedHashMap?


162

Я знаю LinkedHashMap, є передбачуваний порядок ітерації (порядок вставки). Чи підтримує і Setповернутий LinkedHashMap.keySet()і Collectionповернутий LinkedHashMap.values()також цей порядок?


1
Оскільки всі відповіді стосуються питання values(), а також keySet(), я розширив питання, щоб включити це. Це означає, що більше запитань може бути закрито як копії цього.
— Дункан Джонс

Відповіді:


226

Інтерфейс Map надає три представлення колекції , які дозволяють переглядати вміст карти як набір ключів, збір значень або набір відображень ключових значень. Порядок на карті визначаються як порядок , в якому ітератори на вигляді колекційну карти Повернуться їх елементи. Деякі реалізації карт, як-от TreeMap клас, дають конкретні гарантії щодо їх порядку; інші, як і HashMapклас, не роблять.

- Карта

Цей пов'язаний список визначає порядок ітерації, який зазвичай є порядком введення ключів у карту ( порядок вставки ).

- LinkedHashMap

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

В цьому і полягає сенс цього класу.


8
ітерація по карті також робиться швидше за допомогою LinkedHashMap, ніж HashMap.
— Тьєррі

2
values ​​() повертає колекцію. не Список. як це підтримує в порядку?
— Dejell

7
@Dejel Collection- це лише базовий клас для повернення значень (). Реалізація колекції, яку вона повертає, все ще контролюється LinkedHashMap. У LinkedHashMapтакому випадку це повернення LinkedValuesекземпляра, приватного класу всередині LinkedHashMap.java.
— Powerlord

2
Набір клавіш LinkedHashMap в моєму випадку НЕ в порядку, представленому на карті. Дуже спантеличений цим.
— Амальговінус

2
Дякуємо вам за посилання на документацію (від Map), яка явно пов'язує порядок карти з ітераторами на видах колекції карти (і чітко пояснює, що це за представлення колекції). Це був для мене недолік.
— LarsH

11

Дивлячись на джерело, схоже, що це є. keySet(), values()і entrySet()всі використовують один і той же ітератор запису внутрішньо.


1
Було б здорово мати посилання на репост, але я лінивий :-) і звичайно, це не гарантія прямої сумісності.
— Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

6

Не плутайте LinkedHashMap.keySet()і не LinkedHashMap.entrySet()повертайте Комплект, а значить, він не повинен гарантувати замовлення!

Setінтерфейс з HashSet, і TreeSetтак далі істоти його реалізації. HashSetРеалізація Setінтерфейсу не гарантує порядок. Але TreeSetробить. Також LinkedHashSetробить.

Отже, від того, як Setбуло реалізовано, залежить, LinkedHashMapчи гарантуватиме посилання, що повертається, гарантувати замовлення чи ні. Я пройшов вихідний код LinkedHashMap, це виглядає приблизно так:

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

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

Також порядок підтримується тим, як елементи вставляються у відро. Подивіться на addEntry(..)метод LinkedHashMapта порівняйте його з тим, у HashMapякому виділяється основна відмінність між HashMapта LinkedHashMap.


4
Хоча ця відповідь однозначно містить корисну інформацію, вона насправді не відповідає на питання. По суті, вони говорять про те, що вони можуть передбачити порядок ітерації.
— Tuupertunut

5

Можна так припустити. Javadoc говорить "передбачуваний порядок ітерації", і єдиними ітераторами, доступними на карті, є ті, які є для keySet (), entrySet () та значень ().

Отже, за відсутності будь-якої подальшої кваліфікації, явно покликане застосуватись до всіх цих ітераторів.


0

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

Якщо ви хочете забезпечити замовлення, ви, можливо, захочете повторити його на карті і вставити їх у відсортований набір із функцією замовлення на ваш вибір, хоча ви, звичайно, будете платити за ефективність.


Ви маєте на увазі, що entrySet () гарантує замовлення, keySet () не робить?
— користувач256239

1
@kknight: Я не впевнений. javadoc заявляє: "Цей пов'язаний список визначає порядок ітерації, що зазвичай є порядком, в якому ключі були вставлені в карту (порядок вставки).". Однак взагалі JavaDocs для JDK дуже неоднозначні.
— Урі

5
Якщо навіть entrySet () не гарантує порядок ітерації, то яка різниця між LinkedHashMap та HashMap? Як ми можемо скористатися передбачуваним порядком ітерації в екземплярі LinkedHashMap?
— користувач256239

1
Це, безумовно , документально підтверджено. Відповідь абсолютно невірна.
— Маркіз Лорнський

-3

Дивлячись на інтерфейс, він повертає звичайну, Setа не an SortedSet. Тож гарантій немає.

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

Ви можете краще створити, наприклад, TreeSet з keySet в конструкторі.


3
Придивившись до документації, справді є гарантії. Як уже хтось писав, це саме суть цього класу.
— glglgl

-4

Я не думаю, що ви можете припускати впорядкування keySet () та значень ().

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


6
Вся мета LinkedHashMapкласу - зберігати впорядкованість елементів під час ітерації карти, і ця поведінка добре визначена. Якщо ви пишете підклас, не дотримуючись специфікації базового класу, ви робите щось дуже неправильно.
— закінстер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.