有序集合器是否可以在并行流中使用?

6

使用流计算笛卡尔积时,我可以并行生成它们,并按顺序消耗它们,以下代码演示了这一点:

int min = 0;
int max = 9;
Supplier<IntStream> supplier = () -> IntStream.rangeClosed(min, max).parallel();
supplier.get()
        .flatMap(a -> supplier.get().map(b -> a * b))
        .forEachOrdered(System.out::println);

这将按顺序完美打印所有内容,现在考虑以下代码,我想将其添加到列表中,同时保留顺序。
int min = 0;
int max = 9;
Supplier<IntStream> supplier = () -> IntStream.rangeClosed(min, max).parallel();
List<Integer> list = supplier.get()
        .flatMap(a -> supplier.get().map(b -> a * b))
        .boxed()
        .collect(Collectors.toList());
list.forEach(System.out::println);

现在它不按顺序打印!
考虑到我没有要求保留顺序,这是可以理解的。

现在的问题是:是否有一种方法可以collect()或者是否有一个Collector可以保留顺序?


为什么不事先创建列表,然后使用 .forEachOrdered(i -> list.add(i)) 添加元素呢? - fge
@fge,这违背了“Collector”的某些目的,我也不会为普通的顺序收集器这样做。 - skiwi
这只会按顺序输出结果 :-/ - Rohit Jain
1个回答

4
当我执行您的代码时,我按顺序得到了输出。实际上,对于这两段代码,我得到的输出相同。似乎从Collectors.toList返回的Collector已经被排序,如下面的代码所示:
Collector collector = Collectors.toList();
System.out.print(collector.characteristics());

它会输出:

[IDENTITY_FINISH]

由于收集器没有设置UNORDERED特性,因此它只会按顺序处理元素,这就是我所看到的行为。

实际上,这在Collectors.toList()的文档中明确提到:

返回:
一个Collector,它将所有输入元素按照遇到的顺序收集到一个List中。


你说得对,我可能之前看错了,因为我重新测试了一下,它是按顺序执行的。感谢你的确认,加一分! - skiwi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接