EL通过Integer键访问映射值
我有一个由Integer键入的Map。 使用EL,我怎样才能通过它的键访问一个值?
Map<Integer, String> map = new HashMap<Integer, String>(); map.put(1, "One"); map.put(2, "Two"); map.put(3, "Three");
我认为这将工作,但它不(在地图已经在请求的属性):
<c:out value="${map[1]}"/>
跟进:我跟踪了这个问题。 显然${name[1]}
会将数字作为Long
进行地图查找。 当我将HashMap
更改为TreeMap
并收到错误时,我想到了这一点:
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Long
如果我改变我的地图是:
Map<Long, String> map = new HashMap<Long, String>(); map.put(1L, "One");
那么${name[1]}
返回“One”。 那是什么? 为什么<c:out>
把一个数字视为一个长整数。 这似乎违反我的想法(因为int比long更常用)。
所以我的新问题是,是否有一个通过Integer
值访问映射的EL符号?
初步答复(EL 2.1,2009年5月)
正如在这个java论坛主题中提到的:
基本上自动装箱将一个Integer对象放到Map中。 即:
map.put(new Integer(0), "myValue")
EL(expression式语言)将0评估为长,因此在地图中寻找Long作为键。 即它评估:
map.get(new Long(0))
由于Long
不等于Integer
对象,因此它在地图中找不到该条目。
这就是简而言之。
自2009年5月以来的最新情况(EL 2.2)
2009年12月,引入了EL 2.2和JSP 2.2 / Java EE 6 ,与EL 2.1相比有一些不同 。
看来(“ ELexpression式parsing整数一样长 ”):
您可以在EL 2.2中的
Long
对象self上调用intValue
方法 :
<c:out value="${map[(1).intValue()]}"/>
这可能是一个很好的解决方法(下面Tobias Liefke的答案中也提到)
原始答案:
EL使用以下包装器:
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
展示这个的JSP页面:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@ page import="java.util.*" %> <h2> Server Info</h2> Server info = <%= application.getServerInfo() %> <br> Servlet engine version = <%= application.getMajorVersion() %>.<%= application.getMinorVersion() %><br> Java version = <%= System.getProperty("java.vm.version") %><br> <% 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); %> <h3>Looking up map in JSTL - integer vs long </h3> 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. <table border="1"> <tr><th>Key</th><th>value</th><th>Key Class</th></tr> <c:forEach var="entry" items="${myMap}" varStatus="status"> <tr> <td>${entry.key}</td> <td>${entry.value}</td> <td>${entry.key.class}</td> </tr> </c:forEach> </table> <h4> Accessing the map</h4> Evaluating: ${"${myMap['2']}"} = <c:out value="${myMap['2']}"/><br> Evaluating: ${"${myMap[2]}"} = <c:out value="${myMap[2]}"/><br> Evaluating: ${"${myMap[42]}"} = <c:out value="${myMap[42]}"/><br> <p> 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 <p> lifeInteger = <%= lifeInteger %><br/> lifeLong = <%= lifeLong %><br/> lifeInteger.equals(lifeLong) : <%= lifeInteger.equals(lifeLong) %> <br>
除了上面的注释之外,另外一个有用的提示是当你在一些variables中包含一个string值时,比如请求参数。 在这种情况下,将这个传入也将导致JSTL将“1”的值作为一个sting,并在Map哈希映射中找不到匹配。
解决这个问题的一个方法是做这样的事情。
<c:set var="longKey" value="${param.selectedIndex + 0}"/>
这将被视为一个Long对象,然后有一个机会来匹配一个对象,当它包含在地图Map或其他内容中。
然后像往常一样继续
${map[longKey]}
如果您将数字放入“(”“)”“,则可以使用Long中的所有function。 这样你就可以把long赋给int:
<c:out value="${map[(1).intValue()]}"/>
基于上面的post,我试了这个,这工作得很好,我想使用地图B的值作为地图A的键:
<c:if test="${not empty activityCodeMap and not empty activityDescMap}"> <c:forEach var="valueMap" items="${auditMap}"> <tr> <td class="activity_white"><c:out value="${activityCodeMap[valueMap.value.activityCode]}"/></td> <td class="activity_white"><c:out value="${activityDescMap[valueMap.value.activityDescCode]}"/></td> <td class="activity_white">${valueMap.value.dateTime}</td> </tr> </c:forEach> </c:if>
如果你碰巧有一个带有Integer
键的Map
,你不能改变,你可以编写一个自定义的EL函数来把Long
转换为Integer
。 这将允许你做这样的事情:
<c:out value="${map[myLib:longToInteger(1)]}"/>