Java 如何访问forEach内部lambda之外的对象?

Java 如何访问forEach内部lambda之外的对象?,java,lambda,Java,Lambda,我有以下代码: String fields = ""; listofObjects.stream().forEach(l -> fields = fields + l.text); 这不起作用,因为字段应该是最终字段。如何使用lambdas修改字段?实现该功能的最小更改就是使用StringBuilder,这将更有效: StringBuilder builder = new StringBuilder(); listofObjects.stream().forEach(l -> bu

我有以下代码:

String fields = "";
listofObjects.stream().forEach(l -> fields = fields + l.text);

这不起作用,因为
字段
应该是最终字段。如何使用lambdas修改
字段

实现该功能的最小更改就是使用
StringBuilder
,这将更有效:

StringBuilder builder = new StringBuilder();
listofObjects.stream().forEach(l -> builder.append(l.text));
String fields = builder.toString();

正如Martin所指出的,
Collectors.joining()
提供了一般的字符串连接功能,但您需要首先将对象流映射到字符串流。(使用
map
很容易,如果您经常需要这样做,您可以创建自己的收集器来完成。)

流和lambda通常应该是无状态的。以下是针对您的案例的常规解决方案:

String fields = listofObjects.stream()
        .map(l -> l.text)
        .collect(Collectors.joining());

如果您需要执行完全相同的操作:

StringBuilder builder = new StringBuilder();
listofObjects.stream().forEach(l -> builder.append(l.text));
但更实用的方法是

fields = listofObjects.stream().map(l -> l.text).collect(Collectors.joining());
我们可以使用:

或者,根据@shmosel的以下评论:

String fields = listofObjects.stream()
                             .reduce("", String::concat);

您可以执行对象列表。forEach无需
.stream()
始终记住,流lambda可以并行执行-这就是Java保护您不被意外覆盖非最终属性或
的原因。reduce(“,String::concat”)。但是,当有一个更高效的收集器用于此目的时,为什么要使用
reduce()
。@shmosel-true,reduce有另一个重载版本,它接受一个可以使用的初始值。我不认为这样做有任何附加价值,也不认为你提供的解决方案有任何附加价值。您是否看到其中一个函数有赞成/反对的地方?我建议的重载值是它不需要
get()
调用,这通常应该避免。如果要使用
可选
重载,至少要使用
orElse(“”
)来反映OP的意图。收集器的价值在于它可以说更为惯用,因此也更为熟悉。另外,它在内部使用
StringJoiner
,这避免了重复连接的成本。
String fields = listofObjects.stream()
                             .reduce("", String::concat);