Ist die Reihenfolge für die Rückgabe von Schlüsseln und Werten von einem LinkedHashMap-Objekt garantiert?


162

Ich weiß, LinkedHashMaphat eine vorhersehbare Iterationsreihenfolge (Einfügereihenfolge). Wird diese Bestellung auch von der SetRücksendung LinkedHashMap.keySet()und der CollectionRücksendung LinkedHashMap.values()beibehalten?


1
Da alle Antworten das Problem von values()sowie ansprechen keySet(), habe ich die Frage um das erweitert. Dies bedeutet, dass weitere Fragen als Duplikate davon geschlossen werden können.
Duncan Jones

Antworten:


226

Die Kartenschnittstelle bietet drei Sammlungsansichten , mit denen der Inhalt einer Karte als eine Reihe von Schlüsseln, eine Sammlung von Werten oder eine Reihe von Schlüsselwertzuordnungen angezeigt werden kann. Die Reihenfolge einer Karte ist definiert als die Reihenfolge, in der die Iteratoren in den Sammlungsansichten der Karte ihre Elemente zurückgeben. Einige Kartenimplementierungen, wie die TreeMap Klasse, geben spezifische Garantien für ihre Reihenfolge. andere, wie die HashMapKlasse, tun das nicht.

- Karte

Diese verknüpfte Liste definiert die Iterationsreihenfolge, die normalerweise die Reihenfolge ist, in der Schlüssel in die Karte eingefügt wurden ( Einfügereihenfolge ).

- LinkedHashMap

Also, ja, keySet(), values(), und entrySet()(die drei Sammel Ansichten erwähnt) Rückgabewerte in der Reihenfolge der internen verknüpften Liste Anwendungen. Und ja, das JavaDoc dafür Mapund LinkedHashMapgarantiert es.

Das ist schließlich der Punkt dieser Klasse.


8
Die Iteration über die Karte erfolgt mit einer LinkedHashMap auch schneller als mit einer HashMap.
Thierry

2
values ​​() gibt eine Sammlung zurück. keine Liste. Wie hält es es in Ordnung?
Dejell

7
@Dejel Collectionist nur die Basisklasse für die Rückgabe von values ​​(). Die Implementierung der zurückgegebenen Sammlung wird weiterhin von der gesteuert LinkedHashMap. In diesem LinkedHashMapFall wird eine LinkedValuesInstanz zurückgegeben, eine private Klasse in LinkedHashMap.java.
Powerlord

2
Das Keyset einer LinkedHashMap befindet sich in meinem Fall NICHT in der in der Karte angegebenen Reihenfolge. Sehr verwirrt darüber.
Amalgovinus

2
Vielen Dank, dass Sie auf eine Dokumentation (von Map) verlinken, die die Reihenfolge einer Karte explizit mit den Iteratoren in den Sammlungsansichten der Karte verknüpft (und klar macht, um welche Sammlungsansichten es sich handelt). Das war das fehlende Stück für mich.
LarsH

11

Wenn man sich die Quelle ansieht, sieht es so aus. keySet(), values()Und entrySet()alle verwenden die gleichen Eintrag Iterator intern.


1
Es wäre cool, einen Link zu den Repos zu haben, aber ich bin faul :-) und natürlich ist dies keine Garantie für die Vorwärtskompatibilität.
Ciro Santilli 法轮功 冠状 病 六四 事件 13

6

Verwechsle dich nicht mit LinkedHashMap.keySet() und LinkedHashMap.entrySet()Rückkehr Set und daher sollte es keine Garantie für Ihre Bestellung!

Setist eine Schnittstelle mit HashSet, TreeSetetc Wesen ihre Implementierungen. Die HashSetImplementierung der SetSchnittstelle garantiert keine Bestellung. AberTreeSet tut es. Auch LinkedHashSettut.

Daher hängt es davon ab, wie Setimplementiert wurde, um LinkedHashMapzu wissen, ob die zurückgegebene Set-Referenz die Bestellung garantiert oder nicht. Ich habe den Quellcode von durchgesehen LinkedHashMap, es sieht so aus:

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

Somit hat LinkedHashMap / HashMap eine eigene Implementierung von SetdhKeySet . Verwechseln Sie dies also nicht mit HashSet.

Die Reihenfolge wird auch dadurch beibehalten, wie die Elemente in den Bucket eingefügt werden. Schauen Sie sich die addEntry(..)Methode von an LinkedHashMapund vergleichen Sie sie mit der, HashMapdie den Hauptunterschied zwischen HashMapund hervorhebt LinkedHashMap.


4
Diese Antwort enthält zwar definitiv nützliche Informationen, beantwortet die Frage jedoch nicht wirklich. Grundsätzlich heißt es, dass sie eine vorhersehbare Iterationsreihenfolge haben können.
Tuupertunut

5

Das können Sie davon ausgehen. Der Javadoc sagt "vorhersehbare Iterationsreihenfolge", und die einzigen in einer Karte verfügbaren Iteratoren sind die für keySet (), entrySet () und values ​​().

In Ermangelung einer weiteren Qualifikation ist es eindeutig beabsichtigt, auf alle diese Iteratoren anzuwenden.


0

AFAIK ist nicht dokumentiert, so dass Sie dies nicht "formal" annehmen können. Es ist jedoch unwahrscheinlich, dass sich die derzeitige Implementierung ändert.

Wenn Sie die Reihenfolge sicherstellen möchten, können Sie die Karteneinträge durchlaufen und sie in ein sortiertes Set mit einer Bestellfunktion Ihrer Wahl einfügen, obwohl Sie natürlich die Leistungskosten bezahlen.


Meinst du, entrySet () garantiert die Bestellung, keySet () nicht?
user256239

1
@kknight: Ich bin nicht sicher. Im Javadoc heißt es: "Diese verknüpfte Liste definiert die Iterationsreihenfolge, die normalerweise die Reihenfolge ist, in der Schlüssel in die Karte eingefügt wurden (Einfügereihenfolge)." Die JavaDocs für das JDK sind jedoch im Allgemeinen sehr vieldeutig.
Uri

5
Wenn selbst entrySet () die Iterationsreihenfolge nicht garantiert, was ist dann der Unterschied zwischen LinkedHashMap und HashMap? Wie können wir die vorhersagbare Iterationsreihenfolge in einer LinkedHashMap-Instanz nutzen?
user256239

1
Es sicherlich wird dokumentiert. Die Antwort ist völlig falsch.
Marquis von Lorne

-3

Wenn Sie sich die Benutzeroberfläche ansehen, wird eine Ebene Setund keine zurückgegeben SortedSet. Es gibt also keine Garantien.

Bevor Sie eine implizite Garantie übernehmen, indem Sie sich die Implementierung ansehen (immer eine schlechte Idee), schauen Sie sich auch die Implementierungen in allen anderen Java-Implementierungen an :)

Sie können beispielsweise ein TreeSet mit dem keySet im Konstruktor erstellen.


3
Bei näherer Betrachtung der Dokumentation gibt es tatsächlich Garantien. Wie jemand bereits schrieb, ist das genau der Punkt dieser Klasse.
glglgl

-4

Ich glaube nicht, dass Sie die Reihenfolge von keySet () und values ​​() annehmen können.

Ich kann leicht eine Implementierung von LinkedHashMap schreiben, die Ihnen ungeordnetes keySet () und values ​​() zurückgibt, solange ich mich an den Vertrag dieser beiden Methoden halte, die in Map definiert und in HashMap überschrieben werden.


6
Der gesamte Zweck der LinkedHashMapKlasse besteht darin, die Reihenfolge der Elemente während der Iteration der Karte beizubehalten, und dieses Verhalten ist genau spezifiziert. Wenn Sie eine Unterklasse schreiben, ohne die Basisklassenspezifikation einzuhalten, machen Sie etwas sehr Falsches.
Zakinster
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.