【发布时间】:2017-01-22 13:11:18
【问题描述】:
我必须编写一些代码,将 Java 8 Stream 的内容多次添加到 List 中,但我无法确定最好的方法是什么。根据我在 SO(主要是这个问题:How to add elements of a Java8 stream into an existing List)和其他地方阅读的内容,我将其范围缩小到以下选项:
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
public class Accumulator<S, T> {
private final Function<S, T> transformation;
private final List<T> internalList = new ArrayList<T>();
public Accumulator(Function<S, T> transformation) {
this.transformation = transformation;
}
public void option1(List<S> newBatch) {
internalList.addAll(newBatch.stream().map(transformation).collect(Collectors.toList()));
}
public void option2(List<S> newBatch) {
newBatch.stream().map(transformation).forEach(internalList::add);
}
}
这个想法是,对于Accumulator 的同一个实例,这些方法将被多次调用。选择是使用中间列表还是在流外部调用Collection.addAll() 或从流中为每个元素调用collection.add()。
我倾向于选择更符合函数式编程精神的选项 2,并避免创建中间列表,但是,当 n 很大时调用 addAll() 而不是调用 add() 可能会有好处.
这两个选项中的一个明显优于另一个吗?
编辑:JB Nizet 有一个非常酷的answer,它会延迟转换,直到添加了所有批次。在我的情况下,需要立即执行转换。
PS:在我的示例代码中,我使用 transformation 作为需要在流上执行的任何操作的占位符
【问题讨论】:
-
反汇编的字节码(javap)可能会帮助你弄清楚
-
不要进行过早的优化。做任何更清洁的事情,并且只有在遇到性能问题时才使用分析器检查此代码。
-
我认为拨打
addAll()没有任何好处。 -
请注意,如果您进行并行流式处理,结果会有所不同,除非您将
forEach()更改为forEachOrdered()。 -
为什么要求“立即进行转换”?如果您关心“函数式编程的精神”,那么何时执行转换都无关紧要。
标签: java collections java-8 java-stream