Oblicz sumę całkowitą wszystkich liczb w c: pętla forEach

Mam taką Javę:

class Person {
  int age;
  String name;
}

Chciałbym powtórzyć kolekcję tych fasoli w JSP, pokazując każdą osobę w wierszu tabeli HTML, a w ostatnim wierszu tabeli chciałbym pokazać sumę wszystkich grup wiekowych.

Kod do generowania wierszy tabeli będzie wyglądał mniej więcej tak:

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

Jednak ciężko mi znaleźć sposób na obliczenie sumy wieku, która zostanie pokazana w ostatnim wierszu bez uciekania się do kodu skryptowego , sugestie?

Author: BalusC, 2008-09-19

7 answers

uwaga: próbowałem połączyć odpowiedzi, aby stworzyć wyczerpującą listę. Wymieniłem nazwiska tam, gdzie jest to właściwe, aby dać kredyt tam, gdzie jest to należne.

Istnieje wiele sposobów na rozwiązanie tego problemu, z każdym z nich związane są plusy / minusy:]}

Pure JSP Solution

Jak wspomniano powyżej ScArcher2, bardzo łatwym i prostym rozwiązaniem problemu jest zaimplementowanie go bezpośrednio w JSP w taki sposób:

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

Problem z tym rozwiązaniem polega na tym, że JSP staje się mylące do tego stopnia, że równie dobrze mogłeś wprowadzić Skrypty. Jeśli przewidujesz, że każdy, kto spojrzy na stronę, będzie mógł podążać za podstawową logiką, jest to dobry wybór.

Czysty roztwór EL

Jeśli jesteś już na EL 3.0 (Java EE 7 / Servlet 3.1), użyj nowego wsparcia dla strumieni i Lambda :

<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

Inny sposób na wypisanie całości bez wprowadzania kodu scriplet do Twoim JSP jest użycie funkcji EL. Funkcje EL pozwalają na wywołanie statycznej metody publicznej w klasie publicznej. Na przykład, jeśli chcesz iterować nad swoją kolekcją i zsumować wartości, możesz zdefiniować publiczną statyczną metodę o nazwie sum (List people) w klasie publicznej, być może o nazwie PersonUtils. W pliku tld umieścisz następującą deklarację:

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

W Twoim JSP napisałbyś:

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

Funkcje JSP EL mają kilka zalet. Pozwalają na korzystanie z istniejące metody Java bez konieczności kodowania do określonego interfejsu użytkownika (własne biblioteki znaczników). Są również zwarte i nie mylą osoby nie zorientowanej na programowanie.

Niestandardowy Znacznik

Kolejną opcją jest zrolowanie własnego znacznika. Ta opcja będzie obejmować większość konfiguracji, ale da ci to, co myślę, że esentially szukasz, absolutnie bez skryptów. Fajny samouczek do używania prostych niestandardowych tagów można znaleźć na http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/JSPTags5.html#74701

Kroki obejmują 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;
   }
}

Zdefiniuj tag w pliku tld:

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

Zadeklaruj taglib na górze twojego JSP:

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

I użyj tagu:

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

Znacznik Wyświetlania

Jak wspomniano wcześniej zmf, możesz również użyć znacznika display, chociaż będziesz musiał dołączyć odpowiedni biblioteki:

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

 36
Author: Jon-Erik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-01 07:23:19
 3
Author: zmf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-19 15:40:11

/ Align = "center" bgcolor = "# e0ffe0 " / cesarz chin / / align = center /

Można go obliczyć w kontrolerze i wyświetlić tylko wynik w jsp.

Możesz napisać niestandardowy znacznik, aby wykonać obliczenia.

Możesz to obliczyć w jsp używając jstl w ten sposób.

<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}
 3
Author: ScArcher2,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-19 15:44:07

ScArcher2 ma najprostszerozwiązanie . Jeśli chcesz czegoś tak kompaktowego, jak to tylko możliwe, możesz utworzyć bibliotekę tagów z funkcją "sum". Coś w stylu:

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

W Twoim TLD:

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

W Twoim JSP masz coś w stylu:

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

${f:sum(personList)}
 1
Author: James Schek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:16:07

Jest to trochę chwiejne, ale w kodzie kontrolera możesz po prostu stworzyć atrapę obiektu Person z sumą w nim!

Jak odzyskujesz swoje obiekty? HTML pozwala Ci ustawić element, który będzie znajdował się na dole wszystkich danych, dlatego możesz po prostu ustawić sumę oddzielnie od obiektów Person i wypisać ją na stronie jako-jest bez żadnych obliczeń na stronie JSP.

 0
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-19 15:39:10

Możesz iterować nad kolekcją używając JSTL zgodnie z następującym

<c:forEach items="${numList}" var="item">
      ${item}
</c:forEach>

Jeśli jest to mapa, którą możesz zrobić na następującej

<c:forEach items="${numMap}" var="entry">
  ${entry.key},${entry.value}<br/>
</c:forEach>
 0
Author: Brad Larson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-15 02:50:27

Obliczanie sumy / lub innych podsumowań w kontrolerze-Nie w JSP - jest naprawdę zdecydowanie preferowane.

Użyj kodu Javy i podejścia MVC, np. Spring MVC framework, zamiast próbować zrobić zbyt wiele w JSP lub JSTL; wykonywanie znaczących obliczeń w tych językach jest słabe i powolne i sprawia, że strony JSP są znacznie mniej przejrzyste.

Przykład:

class PersonList_Controller implements Controller {
    ...
    protected void renderModel (List<Person> items, Map model) {
        int totalAge = 0;
        for (Person person : items) {
            totalAge += person.getAge();
        }
        model.put("items", items);
        model.put("totalAge", totalAge);
    }
}

Design decision-wise -- wszędzie, gdzie wymagana jest suma, może być w przyszłym miesiącu przedłużony do wymagającego średniej, a mediana, odchylenie standardowe.

Obliczenia i podsumowanie JSTL ledwo trzymają się razem, po prostu uzyskując sumę. Czy naprawdę chcesz spełnić dodatkowe wymagania w JSTL? Uważam, że odpowiedź brzmi NIE -- i dlatego właściwą decyzją projektową jest obliczenie w sterowniku, jako równie / prostsze i zdecydowanie bardziej wiarygodne-wymagania rozszerzalne.

 0
Author: Thomas W,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-30 05:59:02