¿Cómo recorrer un HashMap en JSP?

146

¿Cómo puedo recorrer un HashMapen JSP?

<%
    HashMap<String, String> countries = MainUtils.getCountries(l);
%>

<select name="country">
    <% 
        // Here I need to loop through countries.
    %>
</select>
lloriquear
fuente
17
Por cierto, a HashMapes desordenado por naturaleza. ¿Está seguro de que no necesita TreeMap(clasificación automática por clave) o LinkedHashMap(mantiene el orden de inserción)?
BalusC

Respuestas:

308

De la misma manera que lo haría en un código Java normal.

for (Map.Entry<String, String> entry : countries.entrySet()) {
    String key = entry.getKey();
    String value = entry.getValue();
    // ...
}

Sin embargo , los scriptlets (código Java sin procesar en archivos JSP, esas <% %>cosas) se consideran una mala práctica . Recomiendo instalar JSTL (simplemente suelte el archivo JAR /WEB-INF/liby declare los taglibs necesarios en la parte superior de JSP). Tiene una <c:forEach>etiqueta que puede iterar entre otras Map. Cada iteración le dará un Map.Entryrespaldo que a su vez tiene getKey()y getValue()métodos.

Aquí hay un ejemplo básico:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<c:forEach items="${map}" var="entry">
    Key = ${entry.key}, value = ${entry.value}<br>
</c:forEach>

Por lo tanto, su problema particular se puede resolver de la siguiente manera:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<select name="country">
    <c:forEach items="${countries}" var="country">
        <option value="${country.key}">${country.value}</option>
    </c:forEach>
</select>

Necesita a Servleto a ServletContextListenerpara colocar el ${countries}en el alcance deseado. Si se supone que esta lista está basada en una solicitud, utilice el Servlet's doGet():

protected void doGet(HttpServletRequest request, HttpServletResponse response) {
    Map<String, String> countries = MainUtils.getCountries();
    request.setAttribute("countries", countries);
    request.getRequestDispatcher("/WEB-INF/page.jsp").forward(request, response);
}

O si se supone que esta lista es una constante de toda la aplicación, use ServletContextListener's' contextInitialized()para que se cargue solo una vez y se guarde en la memoria:

public void contextInitialized(ServletContextEvent event) {
    Map<String, String> countries = MainUtils.getCountries();
    event.getServletContext().setAttribute("countries", countries);
}

En ambos casos countries, estará disponible en EL por ${countries}.

Espero que esto ayude.

Ver también:

BalusC
fuente
2
@Khue: sí, también puedes poner atributos en la sesión. Solo que no entiendo por qué le gustaría duplicar los datos de toda la aplicación en varias sesiones.
BalusC
Creo que en caso de información basada en la sesión. Gracias por la muy buena explicación.
Khue Vu
Estoy seguro de que la respuesta es obvia, pero, ¿por qué los scriptlets se consideran una mala práctica? En ausencia de JSTL debido al mantenimiento de una aplicación heredada, esta es mi única opción.
Zibbobz
@Zibbobz: el texto "mala práctica" es un enlace. Haz click en eso.
BalusC
1

Dependiendo de lo que desee lograr dentro del ciclo, repita uno de estos en su lugar:

  • countries.keySet()
  • countries.entrySet()
  • countries.values()
Jim Garrison
fuente
sí, con esto obtengo un conjunto de claves, pero ¿cómo puedo integrarlo en un campo de selección para html?
blub
66
esto no responde a la pregunta que es específica sobre JSP
Taoufik Mohdit
0

El siguiente código me funciona

Primero definí el partnerTypesMapsiguiente como en el lado del servidor,

Map<String, String> partnerTypes = new HashMap<>();

después de agregarle valores, agregué el objeto a model,

model.addAttribute("partnerTypesMap", partnerTypes);

Cuando renderizo la página que uso a continuación foreachpara imprimirlas una por una.

<c:forEach items="${partnerTypesMap}" var="partnerTypesMap">
      <form:option value="${partnerTypesMap['value']}">${partnerTypesMap['key']}</form:option>
</c:forEach>
tk_
fuente