EL tiene acceso a un valor de mapa por clave Integer

Tengo un mapa marcado por Entero. Usando EL, ¿cómo puedo acceder a un valor por su clave?

Map map = new HashMap(); map.put(1, "One"); map.put(2, "Two"); map.put(3, "Three"); 

Pensé que esto funcionaría pero no (donde el mapa ya está en los atributos de la solicitud):

  

Seguimiento: rastreé el problema. Aparentemente, ${name[1]} hace una búsqueda en el mapa con el número Long . Me di cuenta de esto cuando cambié HashMap a TreeMap y recibí el error:

 java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Long 

Si cambio mi mapa para que sea:

 Map map = new HashMap(); map.put(1L, "One"); 

luego ${name[1]} devuelve “One”. ¿Qué hay con eso? ¿Por qué trata a un número como un largo? Parece contradictorio para mí (como int es más comúnmente utilizado que largo).

Entonces mi nueva pregunta es, ¿hay una notación EL para acceder a un mapa por un valor Integer ?

Respuesta inicial (EL 2.1, mayo de 2009)

Como se menciona en este hilo del foro de Java :

Básicamente, el autoboxing pone un objeto entero en el mapa. es decir:

 map.put(new Integer(0), "myValue") 

EL (Expressions Languages) evalúa 0 como Long y por lo tanto busca una Long como la clave en el mapa. es decir, evalúa:

 map.get(new Long(0)) 

Como Long nunca es igual a un objeto Integer , no encuentra la entrada en el mapa.
Eso es todo en pocas palabras.


Actualización desde mayo de 2009 (EL 2.2)

Dic 2009 vio la introducción de EL 2.2 con JSP 2.2 / Java EE 6 , con algunas diferencias en comparación con EL 2.1 .
Parece (” EL Expresión que procesa el entero como el tiempo “) que:

puede llamar al método intValue en el objeto Long self dentro de EL 2.2 :

  

Esa podría ser una buena solución aquí (también mencionada a continuación en la respuesta de Tobias Liefke )


Respuesta original:

EL usa los siguientes envoltorios:

 Terms Description Type null null value. - 123 int value. java.lang.Long 123.00 real value. java.lang.Double "string" ou 'string' string. java.lang.String true or false boolean. java.lang.Boolean 

Página JSP que demuestra esto:

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

Server Info

Server info = <%= application.getServerInfo() %>
Servlet engine version = <%= application.getMajorVersion() %>.<%= application.getMinorVersion() %>
Java version = <%= System.getProperty("java.vm.version") %>
<% Map map = new LinkedHashMap(); map.put("2", "String(2)"); map.put(new Integer(2), "Integer(2)"); map.put(new Long(2), "Long(2)"); map.put(42, "AutoBoxedNumber"); pageContext.setAttribute("myMap", map); Integer lifeInteger = new Integer(42); Long lifeLong = new Long(42); %>

Looking up map in JSTL - integer vs long

This page demonstrates how JSTL maps interact with different types used for keys in a map. Specifically the issue relates to autoboxing by java using map.put(1, "MyValue") and attempting to display it as ${myMap[1]} The map "myMap" consists of four entries with different keys: A String, an Integer, a Long and an entry put there by AutoBoxing Java 5 feature.
KeyvalueKey Class
${entry.key} ${entry.value} ${entry.key.class}

Accessing the map

Evaluating: ${"${myMap['2']}"} =
Evaluating: ${"${myMap[2]}"} =
Evaluating: ${"${myMap[42]}"} =

As you can see, the EL Expression for the literal number retrieves the value against the java.lang.Long entry in the map. Attempting to access the entry created by autoboxing fails because a Long is never equal to an Integer

lifeInteger = <%= lifeInteger %>
lifeLong = <%= lifeLong %>
lifeInteger.equals(lifeLong) : <%= lifeInteger.equals(lifeLong) %>

Otra sugerencia útil además del comentario anterior sería cuando tiene un valor de cadena contenido en alguna variable, como un parámetro de solicitud. En este caso, pasar esto también dará como resultado que JSTL ingrese el valor de decir “1” como aguijón y, como tal, no se encuentre ninguna coincidencia en un mapa hashmap.

Una forma de evitar esto es hacer algo como esto.

  

Esto ahora se tratará como un objeto Largo y luego tendrá la oportunidad de coincidir con un objeto cuando esté contenido dentro del mapa Mapa o lo que sea.

Luego, continúa como de costumbre con algo así como

 ${map[longKey]} 

Puede usar todas las funciones de Long, si coloca el número en “(” “)”. De esa forma puedes lanzar el largo a un int:

  

Basado en la publicación anterior, probé esto y funcionó bien. Quería usar el valor del Mapa B como claves para el Mapa A:

      ${valueMap.value.dateTime}    

Si tiene un Map con las claves Integer que no puede cambiar, podría escribir una función EL personalizada para convertir un Long to Integer . Esto te permitiría hacer algo como: