如何在EL Stream API中使用Collectors#joining?

时间:2019-04-09 13:03:35

标签: tomcat java-stream el

我正在尝试在JSP中将列表的内容打印为单个字符串,并用逗号分隔。

<div>${myList.stream().map(e->e.getStringValue()).collect(Collectors.joining(", "))}</div>

我得到了错误:

javax.el.MethodNotFoundException: Method not found: class org.apache.el.stream.Stream.collect(null)

为什么Tomcat使用其自己的Stream版本? 有没有一种方法可以避免这种情况,并确保当我将它们放在JSP的EL中时,我在java类中编写的内容具有相同的行为?

我找到了这个答案https://stackoverflow.com/a/42930628/2761418 但这不能解决我的问题。它使用Tomcat Streams的自定义方法。

1 个答案:

答案 0 :(得分:4)

EL Stream API未绑定到Java 8的Stream API。 EL Stream API是一个完全独立的API,最初是为与Java 7绑定的Java EE 7开发的。请注意,这确实意味着您在使用EL Stream API时根本不需要Java 8,它已经可以使用在Java 7上。

从历史上看,EL规范负责人试图设计EL Stream API,使其尽可能接近当时所知的Java 8的Stream API提议。不幸的是,由于Stream#join()仅在以后添加,因此EL Collectors#joining()未能通过。

无论如何,您不能在EL Stream方法上使用Java 8的任何Stream API函数,例如Collectors#xxx()。如前所述,EL Stream API完全独立。为了收集EL流,仅Stream#toArray()Stream#toList()Stream#reduce()方法可用。另请参见Java EE教程中的“ Operations on Collection Objects”一章和EL 3.0 specification的第2.3章“集合操作”。

因此,在EL Stream API中,通过加入字符串或任何其他自定义收集器来收集流的最佳选择是使用Stream#reduce()。以下是针对您的具体情况的示例:

<div>${myList.stream().map(e -> e.stringValue).reduce((l, r) -> l += ', ' += r).get()}</div>

请注意,我借此机会将${e.getStringValue()}简化为${e.stringValue},因为它基本上代表了EL中的bean属性。