L'ordre est-il garanti pour le retour des clés et des valeurs d'un objet LinkedHashMap?

162

Je sais qu'il LinkedHashMapa un ordre d'itération prévisible (ordre d'insertion). Est-ce que le Setretour par LinkedHashMap.keySet()et le Collectionretour parLinkedHashMap.values() maintiennent également cette commande?

user256239
la source
1
Étant donné que toutes les réponses abordent la question de values()ainsi que keySet(), j'ai élargi la question pour inclure cela. Cela signifie que plus de questions peuvent être fermées en double.
Duncan Jones

Réponses:

226

L'interface Carte fournit trois vues de collection , qui permettent d'afficher le contenu d'une carte sous la forme d'un ensemble de clés, d'une collection de valeurs ou d'un ensemble de mappages clé-valeur. L' ordre d'une carte est défini comme l'ordre dans lequel les itérateurs sur les vues de collection de la carte renvoient leurs éléments. Certaines implémentations de carte, comme la TreeMap classe, font des garanties spécifiques quant à leur ordre; d'autres, comme la HashMapclasse, ne le font pas.

- Carte

Cette liste chaînée définit l'ordre des itérations, qui est normalement l'ordre dans lequel les clés ont été insérées dans la carte ( ordre d'insertion ).

- LinkedHashMap

Alors, oui, keySet(), values(), et entrySet()(les trois vues de mentioner) les valeurs de retour dans l'ordre des utilisations liste chaînée internes. Et oui, le JavaDoc pour Mapet le LinkedHashMapgarantir.

C'est le but de cette classe, après tout.

Powerlord
la source
8
l'itération sur la carte se fait également plus rapidement en utilisant un LinkedHashMap qu'un HashMap.
Thierry
2
values ​​() renvoie une collection. pas une liste. comment le maintient-il en ordre?
Dejell
7
@Dejel Collectionest juste la classe de base pour ce que renvoie values ​​(). L'implémentation de la collection qu'il renvoie est toujours contrôlée par le LinkedHashMap. Dans ce LinkedHashMapcas, il renvoie une LinkedValuesinstance, une classe privée dans LinkedHashMap.java.
Powerlord
2
Le jeu de clés d'un LinkedHashMap dans mon cas n'est PAS dans l'ordre représenté sur la carte. Très perplexe par cela.
Amalgovinus
2
Merci de Mapcréer un lien vers la documentation (from ) qui lie explicitement l'ordre d'une carte aux itérateurs sur les vues de collection de la carte (et de préciser ce que sont ces vues de collection). C'était la pièce manquante pour moi.
LarsH
11

En regardant la source, on dirait que c'est le cas. keySet(), values()et entrySet()utilisent tous le même itérateur d'entrée en interne.

sblundy
la source
1
Ce serait cool d'avoir un lien vers les dépôts, mais je suis paresseux :-) et bien sûr, ce n'est pas une garantie de compatibilité ascendante.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
6

Ne vous confondez pas avec LinkedHashMap.keySet()etLinkedHashMap.entrySet() revenir ensemble et donc il ne devrait pas garantir la commande!

Setest une interface avec HashSet, TreeSetetc. étant ses implémentations. L' HashSetimplémentation de l' Setinterface ne garantit pas la commande. Mais le TreeSetfait. AussiLinkedHashSet fait .

Par conséquent, cela dépend de la manière dont Seta été implémentée LinkedHashMappour savoir si la référence Set renvoyée garantira la commande ou non. J'ai parcouru le code source de LinkedHashMap, il ressemble à ceci:

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

Ainsi LinkedHashMap / HashMap a sa propre implémentation de SetieKeySet . Alors ne confondez pas cela avecHashSet .

En outre, l'ordre est maintenu par la manière dont les éléments sont insérés dans le seau. Regardez la addEntry(..)méthode de LinkedHashMapet comparez-la avec celle HashMapdont met en évidence la principale différence entre HashMapet LinkedHashMap.

Anzaan
la source
4
Bien que cette réponse présente certainement des informations utiles, elle ne répond pas vraiment à la question. Cela signifie essentiellement qu'ils PEUVENT avoir un ordre d'itération prévisible.
Tuupertunut
5

Vous pouvez le supposer. Le Javadoc dit «ordre d'itération prévisible», et les seuls itérateurs disponibles dans une carte sont ceux pour keySet (), entrySet () et values ​​().

Donc, en l'absence de toute autre qualification, il est clairement destiné à s'appliquer à tous ces itérateurs.

Marquis de Lorne
la source
0

AFAIK il n'est pas documenté donc vous ne pouvez pas "formellement" le supposer. Il est cependant peu probable que la mise en œuvre actuelle change.

Si vous souhaitez assurer l'ordre, vous pouvez parcourir les entrées de la carte et les insérer dans un ensemble trié avec une fonction de commande de votre choix, bien que vous paierez naturellement un coût de performance.

Uri
la source
Voulez-vous dire que entrySet () garantit la commande, pas keySet ()?
user256239
1
@kknight: Je ne suis pas sûr. le javadoc déclare: "Cette liste chaînée définit l'ordre des itérations, qui est normalement l'ordre dans lequel les clés ont été insérées dans la carte (ordre d'insertion).". Cependant, les JavaDocs pour le JDK sont très ambigus en général.
Uri
5
Si même entrySet () ne garantit pas l'ordre d'itération, alors quelle est la différence entre LinkedHashMap et HashMap? Comment tirer parti de l'ordre d'itération prévisible dans une instance LinkedHashMap?
user256239
1
Il certainement est documenté. La réponse est complètement incorrecte.
Marquis de Lorne
-3

En regardant l'interface, il renvoie un simple Setet non un SortedSet. Il n'y a donc aucune garantie.

Avant d'assumer une garantie implicite en regardant l'implémentation (toujours une mauvaise idée) regardez également les implémentations dans toutes les autres implémentations Java :)

Vous pourriez mieux créer par exemple un TreeSet avec le keySet dans le constructeur.

extraneon
la source
3
En regardant de plus près la documentation, il y a en effet des garanties. Comme quelqu'un l'a déjà écrit, c'est le but même de ce cours.
glglgl
-4

Je ne pense pas que vous puissiez présumer l'ordre de keySet () et values ​​().

Je peux facilement écrire une implémentation de LinkedHashMap qui vous renvoie keySet () et values ​​() non ordonnés, tant que je m'en tiens au contrat de ces deux méthodes qui sont définies dans Map et remplacées dans HashMap.

Zoro
la source
6
Le but de la LinkedHashMapclasse est de conserver l'ordre des éléments lors de l'itération de la carte et ce comportement est bien spécifié. Si vous écrivez une sous-classe sans vous conformer à la spécification de la classe de base, vous faites quelque chose de très mal.
zakinster