[java] EL access a map value by Integer key

I have a Map keyed by Integer. Using EL, how can I access a value by its key?

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

I thought this would work but it doesn't (where map is already in the request's attributes):

<c:out value="${map[1]}"/>

Follow up: I tracked down the problem. Apparently ${name[1]} does a map lookup with the number as a Long. I figured this out when I changed HashMap to TreeMap and received the error:

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

If I change my map to be:

Map<Long, String> map = new HashMap<Long, String>();
map.put(1L, "One");

then ${name[1]} returns "One". What's with that? Why does <c:out> treat a number as a long. Seems counterintuitive to me (as int is more commonly used than long).

So my new question is, is there a EL notation to access a map by an Integer value?

This question is related to java jsp jstl el

The answer is


Initial answer (EL 2.1, May 2009)

As mentioned in this java forum thread:

Basically autoboxing puts an Integer object into the Map. ie:

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

EL (Expressions Languages) evaluates 0 as a Long and thus goes looking for a Long as the key in the map. ie it evaluates:

map.get(new Long(0))

As a Long is never equal to an Integer object, it does not find the entry in the map.
That's it in a nutshell.


Update since May 2009 (EL 2.2)

Dec 2009 saw the introduction of EL 2.2 with JSP 2.2 / Java EE 6, with a few differences compared to EL 2.1.
It seems ("EL Expression parsing integer as long") that:

you can call the method intValue on the Long object self inside EL 2.2:

<c:out value="${map[(1).intValue()]}"/>

That could be a good workaround here (also mentioned below in Tobias Liefke's answer)


Original answer:

EL uses the following wrappers:

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 page demonstrating this:

 <%@ 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>

Based on the above post i tried this and this worked fine I wanted to use the value of Map B as keys for Map 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>

Just another helpful hint in addition to the above comment would be when you have a string value contained in some variable such as a request parameter. In this case, passing this in will also result in JSTL keying the value of say "1" as a sting and as such no match being found in a Map hashmap.

One way to get around this is to do something like this.

<c:set var="longKey" value="${param.selectedIndex + 0}"/>

This will now be treated as a Long object and then has a chance to match an object when it is contained withing the map Map or whatever.

Then, continue as usual with something like

${map[longKey]}

If you just happen to have a Map with Integer keys you cannot change, you could write a custom EL function to convert a Long to Integer. This would allow you to do something like:

<c:out value="${map[myLib:longToInteger(1)]}"/>

You can use all functions from Long, if you put the number into "(" ")". That way you can cast the long to an int:

<c:out value="${map[(1).intValue()]}"/>

Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to jsp

Difference between request.getSession() and request.getSession(true) A child container failed during start java.util.concurrent.ExecutionException The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path Using if-else in JSP Passing parameters from jsp to Spring Controller method how to fix Cannot call sendRedirect() after the response has been committed? How to include js and CSS in JSP with spring MVC How to create an alert message in jsp page after submit process is complete getting error HTTP Status 405 - HTTP method GET is not supported by this URL but not used `get` ever? How to pass the values from one jsp page to another jsp without submit button?

Examples related to jstl

Iterating through a List Object in JSP How to get a index value from foreach loop in jstl Get value from hashmap based on key to JSTL How to use if, else condition in jsf to display image Selected value for JSP drop down using JSTL Can not find the tag library descriptor for "http://java.sun.com/jsp/jstl/core" java.lang.ClassNotFoundException: javax.servlet.jsp.jstl.core.Config Adding external resources (CSS/JavaScript/images etc) in JSP Sun JSTL taglib declaration fails with "Can not find the tag library descriptor" How to do if-else in Thymeleaf?

Examples related to el

Identifying and solving javax.el.PropertyNotFoundException: Target Unreachable Adding external resources (CSS/JavaScript/images etc) in JSP How does EL empty operator work in JSF? javax.el.PropertyNotFoundException: Property 'foo' not found on type com.example.Bean How to use && in EL boolean expressions in Facelets? How do I check two or more conditions in one <c:if>? The representation of if-elseif-else in EL using JSF Use JSTL forEach loop's varStatus as an ID What does this expression language ${pageContext.request.contextPath} exactly do in JSP EL? How to access at request attributes in JSP?