it-swarm.com.de

Wie verwende ich eine foreach-Schleife in Java), um die Werte in einer HashMap zu durchlaufen?

Ich versuche den folgenden Code zu kompilieren:

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;
}

Ich erhalte eine Fehlermeldung in der Zeile für:

 inkompatible Typen 
 gefunden: Java.lang.Object 
 benötigt: MyClass.Key 

Die Methode getData() gibt ein Object zurück (in diesem Fall hat das zurückgegebene Object die Struktur HashMap). MyClass.Key Ist eine Aufzählung, die ich für meine Anwendung erstellt habe (in einer anderen Klassendatei - MyClass).

Als ich in MyClass.Java Eine foreach-Schleife mit derselben Struktur erstellt habe, ist dieses Problem nicht aufgetreten.

Was mache ich falsch?

37
troyal

Ein etwas effizienterer Weg, dies zu tun:

  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();

Wenn möglich, definieren Sie "getData", damit Sie die Besetzung nicht benötigen.

42
Paul Tomblin

Veränderung:

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

zu

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

Das Problem ist, dass data.keySet() einen Collection<Object> Zurückgibt, wenn die Daten nur ein Map sind. Sobald Sie es generisch gemacht haben, gibt keySet() einen Collection<MyClass.Key> Zurück. Noch besser ... iterieren Sie über die entrySet(), die ein Collection<MyClass.Key, String> Sein wird. Es vermeidet die zusätzlichen Hash-Lookups.

38
Craig P. Motlin

Ich fand dieses einfache Beispiel unter Java-Forum . Die Syntax ist der foreach-Syntax der Liste sehr ähnlich, nach der ich gesucht habe.

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:] Ich habe es getestet und es funktioniert einwandfrei.

5
dialex

Sie könnten stattdessen das entrySet abrufen, um zu vermeiden, dass die Schlüsselklasse benötigt wird:

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;
}
4

Motlins Antwort ist richtig.

Ich habe zwei Notizen ...

  1. Benutze nicht toString += ..., aber verwenden Sie stattdessen StringBuilder und hängen Sie Daten an.

  2. Die von Martin vorgeschlagene Besetzung gibt Ihnen eine ungeprüfte Warnung, die Sie nicht loswerden können, da sie wirklich unsicher ist.

Ein anderer Weg, ohne Vorwarnung (und mit 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();
}

Dies funktioniert, da die toString-Methode, die Sie für key aufrufen, in der Object-Klasse definiert ist, sodass Sie überhaupt kein Casting benötigen.

Die Verwendung von entrySet ist noch besser, da keine weitere Suche in der Karte erforderlich ist.

3