Как использовать цикл foreach в Java для циклического преобразования значений в 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;
}
Я получаю сообщение об ошибке в строке, в которой говорится:
incompatible types
found : java.lang.Object
required: MyClass.Key
Метод getData()
возвращает Object
(но в этом случае возвращаемый Object
имеет структуру HashMap
). MyClass.Key
- это перечисление, которое я создал для целей моего приложения (в другом файле класса - MyClass
).
Когда я создал цикл foreach с той же структурой в MyClass.java
, я не сталкивался с этой проблемой.
Что я делаю неправильно?
Ответы
Ответ 1
Несколько более эффективный способ сделать это:
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", чтобы вам не нужно было отличать.
Ответ 2
Изменить:
Map data = (HashMap<MyClass.Key, String>) getData();
к
Map<MyClass.Key, String> data = (HashMap<MyClass.Key, String>) getData();
Проблема заключается в том, что data.keySet()
возвращает a Collection<Object>
, если данные являются всего лишь Map
. Когда вы сделаете его общим, keySet()
вернет Collection<MyClass.Key>
. Еще лучше... итерации по entrySet()
, который будет Collection<MyClass.Key, String>
. Это позволяет избежать дополнительных хэш-запросов.
Ответ 3
Я нашел этот простой пример в java-форуме. Синтаксис очень похож на List 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());
}
[EDIT:] Я тестировал его, и он отлично работает.
Ответ 4
Вместо этого вы можете захватить 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;
}
Ответ 5
Ответ Motlin правильный.
У меня есть две заметки...
-
Не используйте toString += ...
, но используйте StringBuilder
вместо этого и добавьте в него данные.
-
В ролях, которые предложил Мартин, вы получите непроверенное предупреждение, от которого вы не сможете избавиться, потому что это действительно опасно.
Другой способ, без предупреждения (и с 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();
}
Это работает, потому что метод toString, который вы вызываете key
, задается в классе Object, поэтому вам вообще не требуется кастинг.
Использование entrySet
еще лучше, так как ему не нужно делать другой поиск на карте.