是否有一种首选方式将列表流收集到一个平面列表中?

时间:2014-09-02 14:52:58

标签: java java-8 java-stream

我想知道,是否有一种首选方法可以从列表流中获取包含流中所有列表元素的集合。 我可以想到两种方法来实现目标:

final Stream<List<Integer>> stream = Stream.empty();
final List<Integer> one = stream.collect(ArrayList::new, ArrayList::addAll, ArrayList::addAll);
final List<Integer> two = stream.flatMap(List::stream).collect(Collectors.toList());

第二个选项对我来说看起来更好,但我想第一个选项在并行流中效率更高。 是否支持或反对这两种方法中的一种?

2 个答案:

答案 0 :(得分:9)

主要区别在于flatMapintermediate operation.collectterminal operation

如果您想立即执行除flatMap之外的其他操作,collect 是处理展平流项目的唯一方式

由于您有两个完全不同语义的相同方法引用collect(ArrayList::new, ArrayList::addAll, ArrayList::addAll),因此进一步ArrayList::addAll非常难以阅读。

关于并行处理,你的猜测是错误的。第一个具有较少的并行处理能力,因为它依赖于应用于流项(子列表)的ArrayList.addAll,这些项不能分解为并行子步骤。相反,如果流中遇到的特定Collectors.toList()支持,flatMap应用于List 可以对子列表项进行并行处理。但只有当你有一个相当小的相当大的子列表流时,这才有意义。

flatMap的唯一缺点是中间流创建,如果您有很多非常小的子列表,则会增加开销。

但是在你的例子中,流是空的,所以它无关紧要(scnr)。

答案 1 :(得分:4)

我认为选项二的意图比选项​​一更清楚。我花了几秒钟的时间来弄清楚第一个发生了什么,它没有看起来&#34;正确&#34; - 虽然它似乎有效。选项二对我来说更明显。

基本上,你所做的是一个平面图。如果是这种情况,我希望看到使用flatmap而不是使用addAll()。