web-dev-qa-db-ja.com

c:forEachループ内のすべての数値の合計を計算します

私はこのようなJava Beanを持っています:

class Person {
  int age;
  String name;
}

これらのBeanのコレクションをJSPで繰り返し、各人をHTMLテーブルの行に表示し、テーブルの最後の行にすべての年齢の合計を表示したいと思います。

テーブルの行を生成するコードは次のようになります。

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

しかし、最後の行に表示される年齢の合計を計算する方法を見つけるのに苦労していますスクリプトレットコードに頼らずに、何か提案はありますか?

17
Dónal

注:回答を組み合わせて包括的なリストを作成してみました。期限が来たときにクレジットを与えるために適切な名前を述べました。

この問題を解決する方法はたくさんあり、それぞれに長所と短所があります。

純粋なJSPソリューション

上記のScArcher2のように、この問題に対する非常に簡単で単純な解決策は、JSPに直接実装することです。

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

このソリューションの問題は、JSPが混乱して、スクリプレットを導入したほうがよいということです。ページを見ているすべての人が、現在の基本的なロジックに従うことができると予想する場合は、それが適切な選択です。

純粋なELソリューション

すでにEL3.0(Java EE 7 /サーブレット3.1)を使用している場合は、 ストリームとラムダ の新しいサポートを使用してください。

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

スクリプレットコードをJSPに導入せずに合計を出力する別の方法は、EL関数を使用することです。 EL関数を使用すると、パブリッククラスでパブリック静的メソッドを呼び出すことができます。たとえば、コレクションを反復処理して値を合計する場合は、PersonUtilsと呼ばれるパブリッククラスでsum(List people)と呼ばれるパブリック静的メソッドを定義できます。 tldファイルに、次の宣言を配置します。

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

JSP内で、次のように記述します。

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

JSPEL関数にはいくつかの利点があります。特定のUI(カスタムタグライブラリ)にコーディングすることなく、既存のJavaメソッドを使用できます。また、コンパクトで、プログラミングを重視しない人を混乱させることはありません。

カスタムタグ

さらに別のオプションは、独自のカスタムタグをロールすることです。このオプションはほとんどのセットアップを含みますが、あなたが本質的に探していると私が思うものをあなたに与えるでしょう、絶対にスクリプトレットはありません。単純なカスタムタグを使用するための優れたチュートリアルは、 http://Java.Sun.com/j2ee/tutorial/1_3-fcs/doc/JSPTags5.html#74701 にあります。

関連する手順には、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;
   }
}

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>

JSPの上部でtaglibを宣言します。

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

タグを使用します:

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

表示タグ

前述のzmfのように、適切なライブラリを含める必要がありますが、displayタグを使用することもできます。

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

39
Jon-Erik

あなたはすべての年齢を合計しようとしていますか?

コントローラで計算して、結果をjspにのみ表示することができます。

計算を行うためのカスタムタグを作成できます。

このようにjstlを使用してjspで計算できます。

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

表示タグを確認してください。 http://displaytag.sourceforge.net/11/tut_basic.html

3
zmf

ScArcher2は最も単純です ソリューション 。できるだけコンパクトなものが必要な場合は、「sum」関数を含むタグライブラリを作成できます。何かのようなもの:

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

TLDの場合:

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

JSPには、次のようなものがあります。

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

${f:sum(personList)}
1
James Schek

少しハッキーですが、コントローラーコードで、合計を含むダミーのPersonオブジェクトを作成できます。

オブジェクトをどのように取得していますか? HTMLを使用すると、データの下部に配置される <TFOOT> 要素を設定できます。したがって、Personオブジェクトとは別に合計を設定し、そのままページに出力することができます。 JSPページでの計算。

0
user7094

次のように、JSTLを使用してコレクションを反復処理できます。

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

それが地図であるならば、あなたは以下ですることができます

<c:forEach items="${numMap}" var="entry">
  ${entry.key},${entry.value}<br/>
</c:forEach>
0
user1374011

コントローラーで(JSPではなく)合計/またはその他の要約を計算することを強くお勧めします。

JSPやJSTLで多くのことをしようとする代わりに、JavaコードとMVCアプローチ(Spring MVCフレームワークなど)を使用します。これらの言語で重要な計算を行うと、弱くて遅くなり、JSPページが作成されます。あまり明確ではありません。

例:

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

意思決定的に設計する-合計が必要な場合は、来月、平均、中央値、標準偏差を必要とするように拡張される可能性があります。

JSTLの計算と要約は、合計を取得するだけで、ほとんどまとめられていません。 JSTLでさらに要約要件を満たしたいと本当に思っていますか?答えはノーだと思います。したがって、正しい設計上の決定は、コントローラーで計算することです。これは、同等に/より単純で、間違いなくより妥当な要件です。

0
Thomas W