Calculate total sum of all numbers in c:forEach loop

56,143

Solution 1

Note: I tried combining answers to make a comprehensive list. I mentioned names where appropriate to give credit where it is due.

There are many ways to solve this problem, with pros/cons associated with each:

Pure JSP Solution

As ScArcher2 mentioned above, a very easy and simple solution to the problem is to implement it directly in the JSP as so:

<c:set var="ageTotal" value="${0}" />
<c:forEach var="person" items="${personList}">
  <c:set var="ageTotal" value="${ageTotal + person.age}" />
  <tr><td>${person.name}<td><td>${person.age}</td></tr>
</c:forEach>
${ageTotal}

The problem with this solution is that the JSP becomes confusing to the point where you might as well have introduced scriplets. If you anticipate that everyone looking at the page will be able to follow the rudimentary logic present it is a fine choice.

Pure EL solution

If you're already on EL 3.0 (Java EE 7 / Servlet 3.1), use new support for streams and lambdas:

<c:forEach var="person" items="${personList}">
  <tr><td>${person.name}<td><td>${person.age}</td></tr>
</c:forEach>
${personList.stream().map(person -> person.age).sum()}

JSP EL Functions

Another way to output the total without introducing scriplet code into your JSP is to use an EL function. EL functions allow you to call a public static method in a public class. For example, if you would like to iterate over your collection and sum the values you could define a public static method called sum(List people) in a public class, perhaps called PersonUtils. In your tld file you would place the following declaration:

<function>
  <name>sum</name>
  <function-class>com.example.PersonUtils</function-class>
  <function-signature>int sum(java.util.List people)</function-signature>
</function> 

Within your JSP you would write:

<%@ taglib prefix="f" uri="/your-tld-uri"%>
...
<c:out value="${f:sum(personList)}"/>

JSP EL Functions have a few benefits. They allow you to use existing Java methods without the need to code to a specific UI (Custom Tag Libraries). They are also compact and will not confuse a non-programming oriented person.

Custom Tag

Yet another option is to roll your own custom tag. This option will involve the most setup but will give you what I think you are esentially looking for, absolutly no scriptlets. A nice tutorial for using simple custom tags can be found at http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/JSPTags5.html#74701

The steps involved include subclassing TagSupport:

public PersonSumTag extends TagSupport {

   private List personList;

   public List getPersonList(){
      return personList;
   }

   public void setPersonList(List personList){
      this.personList = personList;
   }

   public int doStartTag() throws JspException {
      try {
        int sum = 0;
        for(Iterator it = personList.iterator(); it.hasNext()){
          Person p = (Person)it.next();
          sum+=p.getAge();
        } 
        pageContext.getOut().print(""+sum);
      } catch (Exception ex) {
         throw new JspTagException("SimpleTag: " + 
            ex.getMessage());
      }
      return SKIP_BODY;
   }
   public int doEndTag() {
      return EVAL_PAGE;
   }
}

Define the tag in a tld file:

<tag>
   <name>personSum</name>
   <tag-class>example.PersonSumTag</tag-class>
   <body-content>empty</body-content>
   ...
   <attribute>
      <name>personList</name>
      <required>true</required>
      <rtexprvalue>true</rtexprvalue>
      <type>java.util.List</type>
   </attribute>
   ...
</tag>

Declare the taglib on the top of your JSP:

<%@ taglib uri="/you-taglib-uri" prefix="p" %>

and use the tag:

<c:forEach var="person" items="${personList}">
  <tr><td>${person.name}<td><td>${person.age}</td></tr>
</c:forEach>
<p:personSum personList="${personList}"/>

Display Tag

As zmf mentioned earlier, you could also use the display tag, although you will need to include the appropriate libraries:

http://displaytag.sourceforge.net/11/tut_basic.html

Solution 2

Are you trying to add up all the ages?

You could calculate it in your controller and only display the result in the jsp.

You can write a custom tag to do the calculation.

You can calculate it in the jsp using jstl like this.

<c:set var="ageTotal" value="${0}" />
<c:forEach var="person" items="${personList}">
  <c:set var="ageTotal" value="${ageTotal + person.age}" />
  <tr><td>${person.name}<td><td>${person.age}</td></tr>
</c:forEach>
${ageTotal}

Solution 3

Check out display tag. http://displaytag.sourceforge.net/11/tut_basic.html

Solution 4

ScArcher2 has the simplest solution. If you wanted something as compact as possible, you could create a tag library with a "sum" function in it. Something like:

class MySum {
public double sum(List list) {...}
}

In your TLD:

<function>
<name>sum</name>
<function-class>my.MySum</function-class>
<function-signature>double sum(List)</function-signature>
</function>

In your JSP, you'd have something like:

<%@ taglib uri="/myfunc" prefix="f" %>

${f:sum(personList)}
Share:
56,143
Dónal
Author by

Dónal

I earn a living by editing text files. I can be contacted at: [email protected] You can find out about all the different kinds of text files I've edited at: My StackOverflow Careers profile

Updated on August 19, 2021

Comments

  • Dónal
    Dónal over 2 years

    I have a Java bean like this:

    class Person {
      int age;
      String name;
    }
    

    I'd like to iterate over a collection of these beans in a JSP, showing each person in a HTML table row, and in the last row of the table I'd like to show the total of all the ages.

    The code to generate the table rows will look something like this:

    <c:forEach var="person" items="${personList}">
      <tr><td>${person.name}<td><td>${person.age}</td></tr>
    </c:forEach>
    

    However, I'm struggling to find a way to calculate the age total that will be shown in the final row without resorting to scriptlet code, any suggestions?

  • Thomas W
    Thomas W about 11 years
    Calculating Totals in the controller -- not in the JSP -- is really strongly preferable. Use an MVC framework, eg Spring, instead of trying to do too much in JSP or JSTL.
  • Thomas W
    Thomas W about 11 years
    Not versatile -- what property or function-result sum() is meant to compute, cannot be specified. Either you've gone the long way to make a single-purpose operator, or you have to go further & get hacky with reflection to make it versatile.
  • Thomas W
    Thomas W about 11 years
    Short and correct answer: calculate the summary in the Controller, not in JSP.