You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在FreeMarker中用独立集合生成表格列的最优实现方案问询

How to populate a table with two separate Sets in FreeMarker without using a POJO?

I have two independent Sets, and I want to generate a table structured like this:

ColumnA ColumnB
Value1 Value1
Value2 Value2
Value3 Value3
Value4 Value4
Value5 Value6

I know I can achieve this using a POJO, where the two Sets are fields (like a and b) of the POJO, with a template example like this:

<table>
  <tr>
    <th>ColumnA</th>
    <th>ColumnB</th>
  </tr>
  <#list object as c>
    <tr>
      <td>${c.a}</td>
      <td>${c.b}</td>
    </tr>
  </#list>
</table>

But I want to populate ColumnA and ColumnB using the separate Sets directly. I've passed the data with data.put("set1", SET1) and data.put("set2", SET2), but my current template code causes the data to be split into separate rows, which doesn't produce the expected table. What's the optimal way to implement this?


Optimal Solution: Use FreeMarker's ?zip Built-in Function

Since you're working with FreeMarker, the cleanest way to pair elements from your two Sets without wrapping them in a POJO is to leverage the ?zip built-in function. This tool takes two sequences (we'll convert your Sets to sequences first) and pairs their elements into tuples that you can iterate over directly in your template.

Here's the adjusted template code:

<table>
  <tr>
    <th>ColumnA</th>
    <th>ColumnB</th>
  </tr>
  <#list set1?sequence?zip(set2?sequence) as pair>
    <tr>
      <td>${pair[0]!""}</td>
      <td>${pair[1]!""}</td>
    </tr>
  </#list>
</table>

Let me break down the key parts:

  • set1?sequence / set2?sequence: Converts your unordered Sets into ordered sequences. Important: If the order of elements in your table matters, make sure you're using an ordered Set implementation (like LinkedHashSet or TreeSet) when passing data to the template.
  • ?zip: Pairs elements from the two sequences. For example, if set1 contains [Value1, Value2, Value3, Value4, Value5] and set2 contains [Value1, Value2, Value3, Value4, Value6], this creates tuples like (Value1, Value1), (Value2, Value2), etc.
  • ${pair[0]!""} / ${pair[1]!""}: The !"" fallback ensures that if one sequence is shorter than the other, missing elements will show an empty string instead of throwing an error.

Handling Uneven Set Lengths

If one Set is longer than the other, ?zip will stop at the length of the shorter sequence. If you want to include all elements from both Sets (filling empty cells for the shorter one), use this approach:

<table>
  <tr>
    <th>ColumnA</th>
    <th>ColumnB</th>
  </tr>
  <#assign maxLength = (set1?sequence?length > set2?sequence?length) ? set1?sequence?length : set2?sequence?length>
  <#list 0..maxLength-1 as idx>
    <tr>
      <td>${set1?sequence[idx]!""}</td>
      <td>${set2?sequence[idx]!""}</td>
    </tr>
  </#list>
</table>

This code first calculates the length of the longer sequence, then iterates from 0 to that length, pulling elements by index (with fallback to empty string if the index is out of bounds for one sequence).

Quick Notes

  • The ?zip function is available in FreeMarker 2.3.21 and above. If you're stuck on an older version, you'll need to either upgrade or pre-process the Sets into a list of pairs in your Java code before passing them to the template.
  • Always double-check your Set implementation if order matters—standard HashSet doesn't preserve insertion order, which could lead to mismatched rows in your table.

内容的提问来源于stack exchange,提问作者27P

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 08:37:41