37 votes

Comment utiliser une boucle foreach en Java pour parcourir les valeurs d'un HashMap?

Je suis en train de compiler le code suivant:

private String dataToString(){
    Map data = (HashMap<MyClass.Key, String>) getData();
    String toString = "";
    for( MyClass.Key key: data.keySet() ){
        toString += key.toString() + ": " + data.get( key );
    return toString;
}

J'obtiens une erreur dans la ligne qui dit:

des types incompatibles
trouvé : java.lang.Objet
requis: Maclasse.Clé

L' getData() méthode retourne un Object (mais dans ce cas, l' Object retourné a l' HashMap de la structure). MyClass.Key est un enum que j'ai créés pour les besoins de mon application (dans un autre fichier de classe - MyClass).

Quand j'ai créé une boucle foreach avec la même structure en MyClass.java, je n'ai pas rencontrer ce problème.

Ce que je fais mal?

42voto

Paul Tomblin Points 83687

Un moyen légèrement plus efficace de le faire:

   Map<MyClass.Key, String> data = (HashMap<MyClass.Key, String>) getData(); 
  StringBuffer sb = new StringBuffer();
  for (Map.Entry<MyClass.Key,String> entry : data.entrySet()) {
       sb.append(entry.getKey());
       sb.append(": ");
       sb.append(entry.getValue());
   }
   return sb.toString();
 

Si possible, définissez "getData" pour ne pas avoir besoin de la conversion.

38voto

Craig P. Motlin Points 11814

Changement:

 Map data = (HashMap<MyClass.Key, String>) getData();
 

à

 Map<MyClass.Key, String> data = (HashMap<MyClass.Key, String>) getData();
 

Le problème est que data.keySet() renvoie un Collection<Object> si les données sont juste un Map . Une fois que vous en aurez fait un générique, keySet() renverra un Collection<MyClass.Key> . Encore mieux ... parcourez les entrySet() , ce qui sera un Collection<MyClass.Key, String> . Cela évite les recherches supplémentaires dans le hachage.

5voto

DiAlex Points 542

J'ai trouvé cet exemple simple sur le forum java . Sa syntaxe est très similaire à foreach de List , ce que je recherchais.

 import java.util.Map.Entry;
HashMap nameAndAges = new HashMap<String, Integer>();
for (Entry<String, Integer> entry : nameAndAges.entrySet()) {
        System.out.println("Name : " + entry.getKey() + " age " + entry.getValue());
}
 

[EDIT:] Je l'ai testé et cela fonctionne parfaitement.

4voto

Richard Campbell Points 1956

Vous pouvez plutôt saisir entrySet pour éviter d'avoir à utiliser la classe de clé:

 private String dataToString(){    
    Map data = (HashMap<MyClass.Key, String>) getData();    
    String toString = "";    
    for( Map.Entry entry: data.entrySet() ) {        
        toString += entry.getKey() + ": " + entry.getValue();
    }    
    return toString;
}
 

3voto

Peter Štibraný Points 17507

Motlin réponse est bonne.

J'ai deux notes...

  1. Ne pas utiliser toString += ..., mais l'utilisation de StringBuilder au lieu et d'ajouter des données à elle.

  2. Cast qui Martin a suggéré vous donnera décoché avertissement, que vous ne serez pas en mesure de se débarrasser de, car il est vraiment dangereux.

Une autre façon, sans avertissement (et avec StringBuilder):

private String dataToString(){
    Map<?, ?> data = (Map<?, ?>) getData();
    StringBuilder toString = new StringBuilder();
    for (Object key: data.keySet()) {
        toString.append(key.toString());
        toString.append(": ");
        toString.append(data.get(key));
    }
    return toString.toString();
}

Cela fonctionne, parce que la méthode toString qui vous l'appelez key est définie dans la classe Object, de sorte que vous n'avez pas besoin de casting à tous.

À l'aide de entrySet est encore mieux, car il n'a pas besoin de faire une autre recherche dans la carte.

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