Comment itérer une HashMap en Java
Parcourez les entrées d'une HashMap Java avec entrySet, keySet, values, forEach et les streams.
Une HashMap stocke des paires clé-valeur, et tôt ou tard vous aurez besoin de les parcourir — pour afficher un rapport, calculer le total des valeurs ou filtrer des entrées. Java offre plusieurs façons idiomatiques de le faire, chacune adaptée à un besoin légèrement différent : voulez-vous les clés, les valeurs, ou les deux ? Ce chapitre couvre les approches courantes — entrySet(), keySet(), values(), forEach et un Iterator permettant la suppression — et explique quand utiliser chacune.
Ces techniques s'appliquent à toute implémentation de Map, y compris LinkedHashMap et TreeMap, puisqu'elles partagent toutes la même API d'itération.
Parcourir les entrées avec entrySet()
Lorsque vous avez besoin à la fois de la clé et de la valeur, entrySet() est le choix le plus efficace. Il retourne une vue d'objets Map.Entry, et un seul passage vous donne chaque paire sans second lookup :
Map<String, Integer> stock = new HashMap<>();
for (Map.Entry<String, Integer> e : stock.entrySet()) {
System.out.println(e.getKey() + " -> " + e.getValue());
}C'est le choix par défaut recommandé. Utiliser keySet() puis appeler map.get(key) à l'intérieur de la boucle effectue un lookup de hachage redondant par élément ; entrySet() l'évite complètement.
Itérer les clés ou les valeurs séparément
Si vous ne vous intéressez qu'à un côté de chaque paire, demandez uniquement cette vue. keySet() retourne les clés et values() retourne les valeurs :
for (String key : stock.keySet()) {
System.out.println("key: " + key);
}
for (int qty : stock.values()) {
System.out.println("qty: " + qty);
}Les deux vues sont adossées à la map, elles reflètent donc son contenu actuel sans copie. Utilisez keySet() lorsque vous n'avez vraiment pas besoin des valeurs, et values() lorsque les clés sont sans importance.
La méthode forEach
Depuis Java 8, Map dispose d'une méthode forEach qui prend un BiConsumer, vous donnant la clé et la valeur comme paramètres lambda. Elle est concise et se lit bien pour des effets de bord simples :
stock.forEach((key, value) -> System.out.println(key + "=" + value));Il n'y a pas de break ni de continue à l'intérieur d'un lambda, donc pour une sortie anticipée ou un flux de contrôle complexe, une boucle for classique reste plus claire.
Suppression sécurisée avec un Iterator
Modifier structurellement une map pendant qu'une boucle for-each la parcourt lève une ConcurrentModificationException. Pour supprimer des entrées durant la traversée, utilisez un Iterator explicite et appelez sa méthode remove() :
Iterator<Map.Entry<String, Integer>> it = stock.entrySet().iterator();
while (it.hasNext()) {
if (it.next().getValue() < 10) {
it.remove();
}
}Une alternative moderne est stock.entrySet().removeIf(e -> e.getValue() < 10), qui exprime le même filtre en une seule ligne.
| Approche | Donne accès à | Idéale pour |
|---|---|---|
entrySet() | clé + valeur | par défaut ; lecture des deux |
keySet() | clés uniquement | travail sur les clés |
values() | valeurs uniquement | totaux, analyse des valeurs |
forEach | clé + valeur (lambda) | effets de bord concis |
Iterator | clé + valeur | suppression durant la traversée |
Ce qu'il faut retenir de l'exécution :
- La boucle
entrySet()lit chaque clé et valeur en un seul passage et accumuleTotal stock: 39, soit 12 + 7 + 20. keySet()affiche uniquement les clés (apple,banana,cherry) tandis quevalues()affiche uniquement les nombres, montrant que chaque vue expose un côté de la paire.- Le lambda
forEachproduit les mêmes lignes clé=valeur que la boucle manuelle, confirmant qu'il s'agit d'un équivalent concis pour une itération simple. - Un
LinkedHashMapa été utilisé pour que la sortie conserve l'ordre d'insertion — uneHashMapordinaire ne garantit aucun ordre, ses lignes pourraient donc apparaître dans n'importe quelle séquence. - L'appel à
Iterator.remove()supprimebanana(valeur 7, inférieure à 10) et laisse{apple=12, cherry=20}, démontrant une suppression sécurisée en cours de boucle sansConcurrentModificationException.