Чи гарантується порядок повернення ключів та значень об’єкта 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.