I have a list of Player objects getting passed into a JSP from a controller, and I want to display them in a couple of different ways on the same page:
Employ Collections.sort(List, Comparator), providing your own Comparator as required to sort the list into the right order. The java, which could be embedded within <%
and %>
tags, would look something like:
List<Player> list = new ArrayList<Player>();
list.add(new Player()); // populate list
list.add(new Player()); // etc
Collections.sort(list, new Comparator<Player>() {
public int compare(Player o1, Player o2)
{
return o1.getName().compareTo(o2.getName()); // Compare by name, for example
}});
// Now iterations on list will be in 'name' order
for (Player player : list) {
// Display player
}
The SO EL Tag Wiki describes a way to do this without using a scriptlet: using an EL function to do the sort, then using the result for the items
attribute in the JSTL core forEach
tag.
The function class:
package org.hierax.ifdl.tags.player;
public final class PlayerSort {
public static List<Player> sortByRank(List<Player> playerList) {
Collections.sort(playerList, new PlayerSortByRank());
return playerList;
}
public static List<Player> sortByAlias(List<Player> playerList) {
Collections.sort(playerList, new PlayerSortByAlias());
return playerList;
}
}
The TLD:
<?xml version="1.0" encoding="UTF-8" ?>
<taglib
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
version="2.1">
<display-name>Player Functions</display-name>
<tlib-version>1.0</tlib-version>
<short-name>player</short-name>
<uri>org.hierax.ifdl.tags</uri>
<function>
<name>sortByRank</name>
<function-class>org.hierax.ifdl.tags.player.PlayerSort</function-class>
<function-signature>java.util.List sortByRank(java.util.List)</function-signature>
</function>
<function>
<name>sortByAlias</name>
<function-class>org.hierax.ifdl.tags.player.PlayerSort</function-class>
<function-signature>java.util.List sortByAlias(java.util.List)</function-signature>
</function>
</taglib>
The menu JSP:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="p" uri="/WEB-INF/player.tld" %>
<h1>Players</h1>
<p>
<c:forEach items="${p:sortByAlias(model.players)}" var="player">
<a href="<c:url value="/player/${player.id}"/>" class="menuItem">${player.alias}</a>
</c:forEach>
</p>
I'd recommend having two sorted lists in the model. The lists will just contain object references, so it's not a big space issue, and I personally don't like doing that sort of work in the JSPs. If you presort them, it doesn't matter how many times the page is viewed in normal navigation, and as long as the lists don't change, you won't have to incur the sort overhead.