Javaのforeachループを使用してHashMapの値をループするにはどうすればよいですか?
質問
次のコードをコンパイルしようとしています:
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;
}
for行にエラーが表示されます:
incompatible types found : java.lang.Object required: MyClass.Key
getData()
メソッドはObject
を返します(ただし、この場合、返されるHashMap
はMyClass.Key
構造を持ちます)。 MyClass
は、アプリケーションの目的で作成した列挙型です(別のクラスファイル-MyClass.java
)。
<=>で同じ構造のforeachループを作成したとき、この問題は発生しませんでした。
何が間違っているのですか?
解決
これを行うためのもう少し効率的な方法:
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();
可能な限り、<!> quot; getData <!> quot;を定義します。キャストは必要ありません。
他のヒント
変更:
Map data = (HashMap<MyClass.Key, String>) getData();
to
Map<MyClass.Key, String> data = (HashMap<MyClass.Key, String>) getData();
問題は、データが単なるdata.keySet()
の場合、Collection<Object>
がMap
を返すことです。ジェネリックにすると、keySet()
はCollection<MyClass.Key>
を返します。さらに良い... entrySet()
を反復処理します。これはCollection<MyClass.Key, String>
になります。余分なハッシュルックアップを回避します。
javaフォーラムでこの簡単な例を見つけました。 構文は、リストのforeachと非常に似ています。これは私が探していたものです。
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());
}
[編集:]私はそれをテストし、完全に動作します。
代わりにentrySetを取得して、キークラスが不要になるようにすることができます。
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;
}
Motlinの答えは正しいです。
メモが2つあります...
-
toString += ...
は使用せず、代わりにStringBuilder
を使用してデータを追加します。 -
Martinが提案したキャストは未確認の警告を表示しますが、本当に安全ではないため、取り除くことはできません。
別の方法、警告なし(および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();
}
これは機能します。これは、key
で呼び出すtoStringメソッドがObjectクラスで定義されているため、キャストする必要がないためです。
マップで別のルックアップを行う必要がないため、entrySet
を使用するとさらに良い方法になります。