Como faço para usar um loop foreach em Java para percorrer os valores em um HashMap?

StackOverflow https://stackoverflow.com/questions/448122

  •  19-08-2019
  •  | 
  •  

Pergunta

Estou tentando compilar o código a seguir:

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

Eu recebo um erro no para a linha que diz:

incompatible types
found : java.lang.Object
required: MyClass.Key

O método getData() retorna um Object (mas, neste caso, o Object devolvido tem a estrutura HashMap). MyClass.Key é uma enumeração que eu criei para os fins do meu aplicativo (em outro arquivo de classe - MyClass).

Quando eu criei um laço foreach com a mesma estrutura em MyClass.java, eu não encontrar esse problema.

O que estou fazendo de errado?

Foi útil?

Solução

Uma maneira um pouco mais eficiente de fazer isso:

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

Se possível, definir "getData" para que você não precisa do elenco.

Outras dicas

Alterar:

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

para

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

O problema é que data.keySet() retorna um Collection<Object> se os dados é apenas um Map. Uma vez que você torná-lo genérico, keySet() retornará um Collection<MyClass.Key>. Ainda melhor ... iterar sobre os entrySet(), que será um Collection<MyClass.Key, String>. Evita as pesquisas de hash extra.

Eu encontrei este exemplo simples em java fórum . Seu sintaxe é muito semelhante ao foreach da List , que era o que eu estava procurando.

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:]. Eu testei e ele funciona perfeitamente

Você poderia pegar o entrySet em vez disso, para evitar a necessidade da classe chave:

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

A resposta de Motlin está correto.

Eu tenho duas notas ...

  1. Não use toString += ..., mas o uso StringBuilder vez e acrescentar dados a ele.

  2. Elenco qual Martin sugeriu lhe dará aviso desmarcada, que você não será capaz de se livrar, porque é realmente inseguro.

Outra maneira, sem aviso (e com 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();
}

Isso funciona, porque o método toString que você chama em key é definido na classe Object, então você não precisa de fundição em tudo.

Usando entrySet é ainda melhor maneira, uma vez que não precisa fazer um outro olhar-se no mapa.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top