3553 votes

Comment itérer efficacement sur chaque entrée d'une carte Java ?

Si j'ai un objet qui implémente la méthode Map en Java et que je souhaite itérer sur chaque paire qu'elle contient, quelle est la manière la plus efficace de parcourir la carte ?

L'ordre des éléments dépendra-t-il de l'implémentation spécifique de la carte que je possède pour l'interface ?

41 votes

En Java 8, à l'aide d'une expression lambda : stackoverflow.com/a/25616206/1503859

5 votes

5369voto

ScArcher2 Points 22118
Map<String, String> map = ...
for (Map.Entry<String, String> entry : map.entrySet()) {
    System.out.println(entry.getKey() + "/" + entry.getValue());
}

94 votes

Si vous faites cela, cela ne fonctionnera pas car Entry est une classe imbriquée dans Map. java.sun.com/javase/6/docs/api/java/util/Map.html

276 votes

Vous pouvez écrire l'importation comme "import java.util.Map.Entry ;" et cela fonctionnera.

56 votes

@Pureferret La seule raison pour laquelle vous pourriez vouloir utiliser un itérateur est si vous avez besoin d'appeler son remove méthode. Si c'est le cas, cette autre réponse vous montre comment faire. Sinon, la boucle améliorée telle qu'elle est présentée dans la réponse ci-dessus est la solution.

313voto

Saint Hill Points 2285

En Java 8, vous pouvez le faire proprement et rapidement en utilisant les nouvelles fonctionnalités des lambdas :

 Map<String,String> map = new HashMap<>();
 map.put("SomeKey", "SomeValue");
 map.forEach( (k,v) -> [do something with key and value] );

 // such as
 map.forEach( (k,v) -> System.out.println("Key: " + k + ": Value: " + v));

Le type de k et v sera déduit par le compilateur et il n'y a pas besoin d'utiliser la fonction Map.Entry plus.

C'est simple comme bonjour !

12 votes

En fonction de ce que vous voulez faire avec une carte, vous pouvez également utiliser l'API de flux sur les entrées renvoyées par la commande map.entrySet().stream() docs.oracle.com/javase/8/docs/api/java/utilitaire/stream/Stream.html

1 votes

Cela ne fonctionnera pas si vous voulez faire référence à des variables non finales déclarées en dehors de votre expression lambda à partir de la forEach()...

8 votes

@Chris Correct. Cela ne fonctionnera pas si vous essayez d'utiliser effectivement non définitif variables de l'extérieur de la lambda.

253voto

pkaeding Points 12935

Oui, l'ordre dépend de l'implémentation spécifique de Map.

@ScArcher2 utilise la syntaxe Java 1.5, plus élégante. . En 1.4, je ferais quelque chose comme ceci :

Iterator entries = myMap.entrySet().iterator();
while (entries.hasNext()) {
  Entry thisEntry = (Entry) entries.next();
  Object key = thisEntry.getKey();
  Object value = thisEntry.getValue();
  // ...
}

45 votes

Préférez la boucle for au while... for(Iterator entries = myMap.entrySet().iterator() ; entries.hasNext() ; ) {...} Avec cette syntaxe, la portée de 'entries' est réduite à la boucle for uniquement.

8 votes

@jpredham Vous avez raison de dire que l'utilisation de l'option for construire comme for (Entry e : myMap.entrySet) ne vous permettra pas de modifier la collection, mais l'exemple tel que @HanuAthena l'a mentionné devrait fonctionner, puisqu'il vous donne l'élément Iterator dans le champ d'application. (A moins que je ne manque quelque chose...)

1 votes

IntelliJ me donne des erreurs sur Entry thisEntry = (Entry) entries.next(); : ne reconnaît pas Entry . Est-ce un pseudo-code pour quelque chose d'autre ?

142voto

Le code typique pour itérer sur une carte est le suivant :

Map<String,Thing> map = ...;
for (Map.Entry<String,Thing> entry : map.entrySet()) {
    String key = entry.getKey();
    Thing thing = entry.getValue();
    ...
}

HashMap est l'implémentation canonique de la carte et ne fait pas de garanties (ou si elle ne devrait pas changer l'ordre si aucune opération de mutation n'est effectuée sur elle). SortedMap retournera des entrées basées sur l'ordre naturel des clés, ou un Comparator si elle est fournie. LinkedHashMap retournera les entrées dans l'ordre d'insertion ou dans l'ordre d'accès, selon la façon dont il a été construit. EnumMap retourne les entrées dans l'ordre naturel des clés.

(Mise à jour : je pense que ce n'est plus vrai. ) Note, IdentityHashMap entrySet a actuellement une implémentation particulière qui renvoie le même itérateur de type Map.Entry pour chaque élément de la entrySet ! Cependant, à chaque fois qu'un nouvel itérateur avance le Map.Entry est mis à jour.

6 votes

EnumMap a également un comportement particulier, tout comme IdentityHashMap.

1 votes

"LinkedHashMap will either return entries in [...] access-order [...]" ... donc on accède aux éléments dans l'ordre où on y accède ? Soit une tautologie, soit quelque chose d'intéressant qui pourrait utiliser une digression ;-)

5 votes

@jpaugh Seuls les accès directs aux LinkedHashMap compte. Ceux qui passent par iterator , spliterator , entrySet etc., ne modifient pas l'ordre.

105voto

serg10 Points 10157

Il s'agit d'une question en deux parties :

Comment itérer sur les entrées d'une carte ? - @ScArcher2 a répondu à parfaitement.

Quel est l'ordre d'itération - si vous utilisez seulement Map alors, strictement parlant, il y a aucune garantie de commande . Vous ne devriez donc pas vraiment vous fier à l'ordre donné par une implémentation. Cependant, le SortedMap L'interface s'étend Map et fournit exactement ce que vous recherchez - les implémentations donneront toujours un ordre de tri cohérent.

NavigableMap est une autre extension utile - il s'agit d'un SortedMap avec des méthodes supplémentaires pour trouver des entrées par leur position ordonnée dans le jeu de clés. Ainsi, cela peut potentiellement supprimer la nécessité d'itérer en premier lieu - vous pourriez être en mesure de trouver les entrées spécifiques de l'ensemble de clés. entry vous êtes après avoir utilisé le higherEntry , lowerEntry , ceilingEntry ou floorEntry méthodes. Le site descendingMap vous donne même une méthode explicite de inverser l'ordre de passage .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X