Iterando por um HashMap em Java

(Last Updated On: 29 de novembro de 2017)

Estamos desenvolvendo um sistema web para uma empresa de ensino online. Nesse sistema é necessário que o usuário preencha um cadastro inicial, nada muito trabalhoso, apenas o nome, data de nascimento e o estado onde ele reside.

Temos o seguinte formulário de cadastro:

Mas se abrirmos a lista de opções de estados temos o seguinte resultado:

Ele está vazio. Não é isso que queremos. Queremos que quando o usuário abrir a lista de opções a mesma esteja preenchida com as siglas dos estados. Algo assim:

Temos um HashMap com as siglas e os estados e queremos usar para conseguir preencher nosso formulário. Esse HashMap foi feito através do seguinte método:

public HashMap<String, String> getMapa() {
      HashMap<String, String> map = new HashMap<>();
      map.put("AC", "Acre");
      map.put("AL", "Alagoas");
      map.put("AP", "Amapá");
      map.put("AM", "Amazonas");
      map.put("BA", "Bahia");
      map.put("CE", "Ceará");
      map.put("DF", "Distrito Federal");
      map.put("ES", "Espírito Santo");
      map.put("GO", "Goiás");
 	    //resto dos put()
      return map;
}

Para conseguir retornar apenas as siglas, ou seja, as chaves, vamos usar o método keySet() da classe Map. Ele nos devolve um Set, que, basicamente, é uma coleção de elementos únicos, logo, não se repetem.

Agora vamos iterar sobre o retorno desse método para vermos se nosso método está realmente retornando todas as siglas:

HashMap<String, String> mapaEstados = getMapa();
   for (String sigla : mapaEstados.keySet()) {
      System.out.print(sigla + " ");
   }

Ao executar esse código, obtemos o seguinte resultado:

Funcionou! Mas como faríamos para mostrar esse resultado na web?

Podemos usar uma JSP. Para conseguir o resultado esperado, só precisamos iterar os valores, desse jeito:

<c:forEach items="${mapaEstados.keySet()}" var="sigla">
   <option>${sigla}</option>
</c:forEach>

E aí, visualizando o formulário:

Uma outra abordagem muito comum é o value da tag option ser a sigla, mas exibir o nome do estado por extenso. Ou seja, por exemplo, o value ser SP, só que o usuário veria São Paulo. Vamos tentar fazer isso?

Para alcançar tal resultado, precisamos tanto da chave quanto do valor do mapa. Para conseguirmos ambos, podemos usar o método entrySet() da classe Map. Ele nos devolve um Set<Map.Entry<K, V>>, onde K e V são os tipos da chave e do valor respectivamente do nosso mapa. Esse retorno nada mais é do que uma entrada contendo a chave e seu respectivo valor.

Vamos iterar esse entrySet():


for (Map.Entry<String, String> entrada : mapaEstados.entrySet()) {
   System.out.println(entrada);
}

Como resultado desse código, temos o seguinte:

Mas perceba que essa forma não é ideal, pois não conseguimos manusear de forma eficaz a chave e o valor. Conseguimos, apenas, a entrada inteira e ainda com um sinal de igual horrível no meio. Para resolve isso, vamos usar os métodos getKey() e getValue() de Map.Entry:

HashMap<String, String> mapaEstados = getMapa();
   for (Map.Entry<String, String> entrada : mapaEstados.entrySet()) {
      System.out.println(entrada.getKey());
      System.out.println(entrada.getValue());
}

E como resultado, temos:

Cada chave está associada ao seu valor, está tudo correto. Agora, se fossemos implementar na JSP, teríamos que usar os métodos na JSP. Dessa forma:

<c:forEach items="${mapaEstados.entrySet()}" var="entrada">
   <option value="${entrada.key}">${entrada.value}</option>
</c:forEach>

Se olharmos o código html, temos o seguinte:

<select>
<option value="RR">Boa Vista</option>
<option value="RS">Porto Alegre</option><br />
<option value="DF">Brasília</option>
//outros options
</select>

Perceba que está exatamente do jeito que queríamos, o value é a sigla e para o usuário aparece os estados por extenso.

Se quiséssemos apenas os estados por extenso para o usuário escolher, sem precisar atribuir a chave como o value da tag option, poderíamos usar o método values() que retorna uma coleção contendo os valores do mapa. Assim:

HashMap<String, String> mapaEstados = getMapa();
   for (String valor : mapaEstados.values()) {
      System.out.println(valor);
    }

Ao executar esse código:

Agora na JSP:

<c:forEach items="${mapaEstados.values()}" var="estado">
   <option>${estado}</option>
</c:forEach>

Voltando ao primeiro exemplo, caso nossa lista de estados contivesse apenas as siglas e, em outra tela, por exemplo uma tela de confirmação, onde mostrasse os dados que o usuário preencheu, quiséssemos mostrar o estado por extenso referente a sigla que o usuário escolheu, como faríamos?

Podemos criar um método que recebe como parâmetro a sigla escolhida e usar o método get() da interface Map para pegar seu respectivo valor. Dessa forma:

public static String pegaEstadoPorExtenso(String sigla){
        HashMap<String, String> mapa = getMapa();
        return mapa.get(sigla);
}

Para testarmos, vamos mandar a sigla RJ:

System.out.println(pegaEstadoPorExtenso("RJ"));

O resultado é exatamente o que esperamos:

Desenvolvemos tudo o que foi pedido de forma eficiente e limpa, parabéns!

Para saber mais

Todas as iterações que fizemos para testar nossos métodos poderiam ter sido feitas usando programação funcional, uma feature trazida com o Java 8. Por exemplo, para imprimir as siglas:

mapaEstados.keySet().stream().forEach(System.out::println);

Para imprimir as chaves e os valores:

mapaEstados.forEach((sigla, estado) -> System.out.println(sigla + " " + estado));

E por fim, os valores usando o values()

mapaEstados.values().stream().forEach(System.out::println);

Se quiser conhecer mais sobre as milhares de funcionalidades trazidas pelo Java 8 confira o curso Java 8: Tire proveito dos novos recursos da linguagem da Alura.

E aí, já teve que usar um Map no seu cotidiano? Comente aqui sua experiência a respeito dessa estrutura de dados.

Quer dominar de vez mapas e coleções? Aqui na Alura temos o Curso Java: Dominando as Collections. Lá é mostrado a fundo cada coleção e, também, possui um capítulo só sobre mapas. Vale muito a pena dar uma conferida.

FIQUE POR DENTRO

  • Paulo Silveira

    muito bom o artigo e agradeço a citação aos meus cursos 🙂

    • Mario Alvial

      Obrigado Paulo. Parabéns pelos cursos! São muito bons.

Próximo ArtigoVocê conhece o princípio de Gestalt?