Czy kolejność jest gwarantowana dla zwrotu kluczy i wartości z obiektu LinkedHashMap?

162

Wiem, że LinkedHashMapma przewidywalną kolejność iteracji (kolejność reklamowa). Czy Setzwracane przez LinkedHashMap.keySet()i Collectionzwracane przez LinkedHashMap.values()klienta również utrzymują to zamówienie?

user256239
źródło
1
Ponieważ wszystkie odpowiedzi rozwiązania problemu values(), a także keySet(), mam pytanie rozszerzony obejmuje to. Oznacza to, że więcej pytań można zamknąć jako duplikaty tego.
Duncan Jones

Odpowiedzi:

226

Interfejs mapy udostępnia trzy widoki kolekcji , które umożliwiają przeglądanie zawartości mapy jako zestawu kluczy, zbioru wartości lub zestawu odwzorowań klucz-wartość. Zamówienie z mapy jest zdefiniowany jako takiej kolejności, w której iteratory widokiem na zbiorach MAP wrócić do swoich elementów. Niektóre implementacje map, takie jak TreeMap klasa, dają określone gwarancje co do ich kolejności; inni, jak HashMapklasa, nie.

- Mapa

Ta połączona lista definiuje kolejność iteracji, która zwykle jest kolejnością, w której klucze zostały wstawione do mapy ( kolejność wstawiania ).

- LinkedHashMap

Tak, tak keySet(), values(), i entrySet()(trzy widoki kolekcja wspomniano) wartości zwracane w kolejności wewnętrznych związanych zastosowań listy. I tak, JavaDoc Mapi LinkedHashMapgwarantuje to.

W końcu o to chodzi w tej klasie.

Władca
źródło
8
iteracja po mapie jest również wykonywana szybciej przy użyciu LinkedHashMap niż HashMap.
Thierry
2
values ​​() zwraca kolekcję. nie jest listą. jak to utrzymuje w porządku?
Dejell
7
@Dejel Collectionjest po prostu klasą bazową zwracanych wartości (). Implementacja kolekcji, którą zwraca, jest nadal kontrolowana przez LinkedHashMap. W tym LinkedHashMapprzypadku zwraca LinkedValuesinstancję, prywatną klasę wewnątrz LinkedHashMap.java.
Powerlord
2
Zestaw kluczy LinkedHashMap w moim przypadku NIE jest w kolejności przedstawionej na mapie. Bardzo to zdziwiło.
Amalgovinus
2
Dziękujemy za łącze do dokumentacji (z Map), która wyraźnie wiąże kolejność mapy z iteratorami w widokach kolekcji mapy (i wyjaśnienie, czym są te widoki kolekcji). To był dla mnie brakujący element.
LarsH
11

Patrząc na źródło, wygląda na to, że tak. keySet(), values()i entrySet()wszystkie używają wewnętrznie tego samego iteratora wpisu.

sblundy
źródło
1
Fajnie byłoby mieć link do repozytoriów, ale jestem leniwy :-) i oczywiście nie gwarantuje to kompatybilności w przód.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
6

Nie daj się mylić z LinkedHashMap.keySet()i LinkedHashMap.entrySet()powracającego ustawiony i dlatego nie powinny gwarantować zamawiania!

SetJest to interfejs HashSet, TreeSetitp istoty jego implementacje. HashSetImplementacja Setinterfejsu nie gwarantuje uporządkowanie. Ale TreeSettak. Też LinkedHashSet.

W związku z tym zależy to od tego, w jaki sposób Setzostało zaimplementowane, LinkedHashMapaby wiedzieć, czy zwracane odniesienie do zestawu zagwarantuje zamówienie, czy nie. Przejrzałem kod źródłowy LinkedHashMap, wygląda to tak:

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

Zatem LinkedHashMap / HashMap ma własną implementację Settj KeySet. Dlatego nie myl tego zHashSet .

Kolejność jest również utrzymywana przez sposób wkładania elementów do wiadra. Spójrz na addEntry(..)metodę LinkedHashMapi porównaj ją z tą, HashMapktóra podkreśla główną różnicę między HashMapi LinkedHashMap.

anzaan
źródło
4
Chociaż ta odpowiedź zdecydowanie zawiera przydatne informacje, tak naprawdę nie odpowiada na pytanie. Zasadniczo oznacza to, że MOGĄ mieć przewidywalną kolejność iteracji.
Tuupertunut
5

Możesz tak założyć. Javadoc mówi „przewidywalna kolejność iteracji”, a jedynymi dostępnymi iteratorami na mapie te dla keySet (), entrySet () i values ​​().

Tak więc w przypadku braku dalszych zastrzeżeń, jest to wyraźnie przeznaczone do zastosowania do wszystkich tych iteratorów.

Markiz Lorne
źródło
0

AFAIK nie jest to udokumentowane, więc nie można tego "formalnie" założyć. Jest jednak mało prawdopodobne, aby obecna implementacja uległa zmianie.

Jeśli chcesz zapewnić porządek, możesz iterować po wpisach mapy i wstawić je do posortowanego zestawu z wybraną funkcją kolejności, chociaż oczywiście będziesz płacić za wydajność.

Uri
źródło
Czy masz na myśli entrySet () gwarantuje porządek, a keySet () nie?
user256239
1
@kknight: Nie jestem pewien. javadoc stwierdza: „Ta połączona lista definiuje kolejność iteracji, która jest zwykle kolejnością, w której klucze zostały wstawione do mapy (kolejność wstawiania).”. Jednak JavaDocs dla JDK są ogólnie bardzo niejednoznaczne.
Uri
5
Jeśli nawet entrySet () nie gwarantuje kolejności iteracji, jaka jest różnica między LinkedHashMap i HashMap? Jak możemy wykorzystać przewidywalną kolejność iteracji w instancji LinkedHashMap?
user256239
1
Z całą pewnością jest to udokumentowane. Odpowiedź jest całkowicie błędna.
Markiz Lorne
-3

Patrząc na interfejs, zwraca zwykły, Seta nie plik SortedSet. Więc nie ma żadnych gwarancji.

Przed założeniem niejawnej gwarancji, patrząc na implementację (zawsze zły pomysł), spójrz także na implementacje we wszystkich innych implementacjach Java :)

Możesz lepiej utworzyć na przykład TreeSet z zestawem kluczy w konstruktorze.

extraneon
źródło
3
Przyglądając się bliżej dokumentacji, rzeczywiście istnieją gwarancje. Jak ktoś już napisał, o to właśnie chodzi w tej klasie.
glglgl
-4

Nie sądzę, aby można było założyć kolejność keySet () i wartości ().

Mogę łatwo napisać implementację LinkedHashMap, która zwraca ci unordered keySet () i values ​​(), o ile trzymam się kontraktu tych dwóch metod, które są zdefiniowane w Map i nadpisane w HashMap.

Zoro
źródło
6
Celem LinkedHashMapklasy jest zachowanie kolejności elementów podczas iteracji mapy, a to zachowanie jest dobrze określone. Jeśli piszesz podklasę bez przestrzegania specyfikacji klasy bazowej, robisz coś bardzo złego.
zakinster