私は次のコードをコンパイルしようとしています:
_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行に次のようなエラーが表示されます。
互換性のないタイプ found:Java.lang.Object required:MyClass.Key
getData()
メソッドはObject
を返します(ただし、この場合、返される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();
可能な場合は、キャストを必要としないように「getData」を定義します。
変化する:
_Map data = (HashMap<MyClass.Key, String>) getData();
_
に
_Map<MyClass.Key, String> data = (HashMap<MyClass.Key, String>) getData();
_
問題は、データが単なるMap
の場合、data.keySet()
が_Collection<Object>
_を返すことです。汎用化すると、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;
}
モトリンの答えは正しいです。
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
を使用すると、マップで別のルックアップを行う必要がないため、さらに良い方法です。