How to break and display one ArrayList into multip

2019-02-19 13:23发布

I have a servlet which loads a properties file and contains a list of 100 test case names into an ArrayList object. After loading the servlet forwards to a JSP which displays the list in a table. The list is long so I would like some elegant way to display it in a table so that it breaks up into, for example, three or four columns on the JSP.

What I do now is break up the list into three sublists in the servlet:

//load properties
Properties props = new Properties();
        ArrayList<String> tests = new ArrayList<String>();
        props.load(getServletContext().getResourceAsStream("/WEB-INF/sailcertifier.properties"));
        Pattern pattern = Pattern.compile("[A-Z]{3}-[0-9]{2}");     
        for (Enumeration<Object> e = props.keys(); e.hasMoreElements();) {
            String key = (String) e.nextElement();
            Matcher m = pattern.matcher(key);
            if (m.find())
                tests.add(key);
        }
        Collections.sort(tests, new TestOrderComparator());
        confBean.setPossibleTests(tests.toArray(new String[tests.size()]));
        int third = tests.size() / 3;
        List<String> testSubset1 = tests.subList(0, third);
        List<String> testSubset2 = tests.subList(third, third * 2);
        List<String> testSubset3 = tests.subList(third * 2, tests.size());
        //store the bean as a request attribute
        request.setAttribute("testSet1", testSubset1.toArray(new String[testSubset1.size()]));
        request.setAttribute("testSet2", testSubset2.toArray(new String[testSubset2.size()]));
        request.setAttribute("testSet3", testSubset3.toArray(new String[testSubset3.size()]));
        request.setAttribute("testsConf", confBean);
        request.setAttribute("certProps", props);
        //forward to tests selection page
        String url = "/sailcertifier/jsp/testsSelection.jsp";
        RequestDispatcher dispatcher = getServletContext().getRequestDispatcher(url);
        response.setContentType("application/javascript");
        try {
            dispatcher.forward(request, response);
        } catch (ServletException e) {
            e.printStackTrace();
        }

In the JSP I iterate through the sublists like so (adding some html elements for each case):

    <table>
        <tr>
            <td style="width: 33%">
                <table>
                    <tr>
                        <td>
                            <c:forEach var="testName" items="${testSet1}">
                                <tr>
                                    <td><label for="${testName}" id=${testName}Label>${testName}</label></td>
                                    <td><input id=${testName} type="checkbox" value=${testName} name="selTest"></input></td>
                                    <td><input id=${testName}Run type="button" value="Run Test" name="runButtons" /></td>
                                    <td><input id=${testName}ManPass type="button" value="Manual Pass" name="manPassButtons"/></td>
                                    <td><div id=${testName}Status style="width:100px"></td>
                                    <td></td>
                                    <td></td>
                                </tr>
                            </c:forEach>
                            <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
                        </td>
                    </tr>
                </table>
            </td>
            <td style="width: 33%">
                <table>
                    <tr>
                        <td>
                            <c:forEach var="testName" items="${testSet2}">
                                <tr>
                                    <td><label for="${testName}" id=${testName}Label>${testName}</label></td>
                                    <td><input id=${testName} type="checkbox" value=${testName} name="selTest"></input></td>
                                    <td><input id=${testName}Run type="button" value="Run Test" name="runButtons" /></td>
                                    <td><input id=${testName}ManPass type="button" value="Manual Pass" name="manPassButtons"/></td>
                                    <td><div id=${testName}Status style="width:100px"></td>
                                    <td></td>
                                    <td></td>
                                </tr>
                            </c:forEach>
                            <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
                        </td>
                    </tr>
                </table>
            </td>
            <td style="width: 33%">
                <table>
                    <tr>
                        <td>
                            <c:forEach var="testName" items="${testSet3}">
                                <tr>
                                    <td><label for="${testName}" id=${testName}Label>${testName}</label></td>
                                    <td><input id=${testName} type="checkbox" value=${testName} name="selTest"></input></td>
                                    <td><input id=${testName}Run type="button" value="Run Test" name="runButtons" /></td>
                                    <td><input id=${testName}ManPass type="button" value="Manual Pass" name="manPassButtons"/></td>
                                    <td><div id=${testName}Status style="width:100px"></td>
                                    <td></td>
                                </tr>
                            </c:forEach>
                        </td>
                    </tr>
                </table>
            </td>
        </tr>
    </table>

I admit using three JSTL for loops is kind of ugly (haven't figured out use the full original list yet). Is there a cleaner way to handle this, by using some jquery plugin (like jquery grid plugin) or other library (displaytag?) to handle the breaking up into rows evenly for me?

2条回答
再贱就再见
2楼-- · 2019-02-19 13:33

i'm not sure i've understood your request but suppose you have your 100 elements array and you want 3 columns to display them, so you can exploit "float" property to achieve that: just make a div of the width you want and iterate over the arrays making inner divs of width/3:

     <div style="width:600px;margin:auto;">
          <c:forEach var="testName" items="${testSet}">
              <div style="float:left;width:200px;">whatever you want to do with ${testName}</div>
          </c:forEach>
     </div>
查看更多
▲ chillily
3楼-- · 2019-02-19 13:51

Print a <tr>, then loop over the array list, then print each item in a <td> and print a </tr><tr> every n items, then end the loop over the array list and finally print a </tr> afterwards.

E.g. a new row every 3rd item:

<table>
    <tr>
        <c:forEach items="${items}" var="item" varStatus="loop">
            <c:if test="${not loop.first and loop.index % 3 == 0}">
                </tr><tr>
            </c:if>
            <td>${item}</td>
        </c:forEach>
    </tr>
</table>

The ${loop.index} returns the index of the current iteration round. The % 3 would only return 0 if it is dividable by 3 without a remainder (thus, when the index is 0, 3, 6, 9, 12, etc).

查看更多
登录 后发表回答