EL, Tamsayı anahtarıyla bir harita değerine erişir


85

Tamsayı ile anahtarlanmış bir Haritam var. EL kullanarak, bir değere anahtarıyla nasıl erişebilirim?

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

Bunun işe yarayacağını düşündüm ama işe yaramıyor (haritanın zaten isteğin özelliklerinde olduğu yerlerde):

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

Takip: Sorunun izini sürdüm. Görünüşe göre ${name[1]}bir numara ile harita araması yapıyor Long. Değiştim ben bu out düşündüm HashMapetmek TreeMapve hata aldı:

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

Haritamı şöyle değiştirirsem:

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

sonra ${name[1]}"Bir" değerini döndürür. Bunun nesi var? Neden <c:out>bir sayıya uzun muamele ediyor? Bana mantığa aykırı görünüyor (int, long'dan daha yaygın olarak kullanıldığından).

Öyleyse yeni sorum şu, bir haritaya bir Integerdeğere göre erişmek için bir EL gösterimi var mı?

Yanıtlar:


117

İlk cevap (EL 2.1, Mayıs 2009)

Bu java forum başlığında belirtildiği gibi :

Temel olarak otomatik kutulama, Haritaya bir Tamsayı nesnesi koyar. yani:

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

EL (İfade Dilleri) 0'ı Uzun olarak değerlendirir ve bu nedenle haritada anahtar olarak Uzun'u arar. yani şunları değerlendirir:

map.get(new Long(0))

A Longhiçbir zaman bir Integernesneye eşit olmadığından, haritada girişi bulamaz.
Özetle bu.


Mayıs 2009'dan beri güncelleme (EL 2.2)

Aralık 2009 JSP 2.2 / Java EE 6 ile EL 2.2 tanıtımı gördüm bir ile, EL 2.1 ile karşılaştırıldığında bazı farklılıklar .
Görünüşe göre (" EL İfadesi tamsayıyı uzun süre ayrıştırıyor "):

Eğer yöntemini çağırabilirsiniz intValueüzerine LongEL 2.2 içindeki nesne öz :

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

Yani burada iyi bir geçici çözüm olabilir (ayrıca aşağıda belirtilen Tobias Liefke 'ın cevabı )


Orijinal cevap:

EL, aşağıdaki sarmalayıcıları kullanır:

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

Bunu gösteren JSP sayfası:

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

Öyleyse EL'in bir sayıyı Tamsayı olarak genişletmesini sağlamanın bir yolu yok mu?
Steve Kuo

1
@Steve: Gerçekten, EL bunu desteklemiyor gibi görünüyor.
VonC

Bu soruyu ve yanıtı bir Google aramasından buldum. Yeterince kesin, Map <Integer, String> 'ten Map <Long, String>' e geçer geçmez, JSP sayfamda sahip olduğum EL'yi kullanarak buradan çekebildim. Teşekkürler!!
John Munsch

@Steve: Mümkün - cevabımı görün
Tobias Liefke

@SteveKuo Gerçekten mümkün olmalı. Şimdi, bu 6 yıllık cevabın EL 2.2 henüz piyasaya sürülmediğinde yazıldığını anlıyorum. Söz konusu cevabı düzenledim ve güncelledim.
VonC

11

Yukarıdaki yoruma ek olarak bir başka yardımcı ipucu da, istek parametresi gibi bazı değişkenlerde bulunan bir dize değerine sahip olduğunuz zamandır. Bu durumda, bunu iletmek aynı zamanda JSTL'nin "1" sayısının değerini bir iğne olarak anahtarlamasına ve bu nedenle bir Harita karma haritasında hiçbir eşleşme bulunmamasına neden olacaktır.

Bunu aşmanın bir yolu, böyle bir şey yapmaktır.

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

Bu artık bir Uzun nesne olarak ele alınacak ve daha sonra harita Haritası veya her neyse içerdiği bir nesneyi eşleştirme şansı olacak.

Ardından, her zamanki gibi devam edin

${map[longKey]}

10

Numarayı "(" ")" içine girerseniz, Long'daki tüm işlevleri kullanabilirsiniz. Bu şekilde long'u bir int'e çevirebilirsiniz:

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

Cevabınızı hemen görmedim. +1. Daha fazla görünürlük için bu olasılığı cevabıma ekledim ve belgeledim.
VonC

3

Yukarıdaki gönderiye dayanarak bunu denedim ve bu işe yaradı, Harita B'nin değerini Harita A için anahtar olarak kullanmak istedim:

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

3

Eğer sadece bir yoluna sahip olması halinde Mapolan Integerdeğiştiremediğiniz tuşları, bir yazabilirsiniz özel EL işlevi bir dönüştürme Longiçin Integer. Bu, aşağıdaki gibi bir şey yapmanıza izin verir:

<c:out value="${map[myLib:longToInteger(1)]}"/>
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.