有没有一种方法可以压缩两个流?

5
这个问题源于另一个问题的答案,其中建议使用map和reduce并行计算总和。
在那个问题中有一个complexCalculation(e),但现在我想知道如何进一步并行化,将计算分为两部分,使得complexCalculation(e)=part1(e)*part2(e)。我想知道是否可能在集合上并发地计算part1和part2(再次使用map()),然后压缩两个结果流,以便第i个元素与函数*相结合,从而得到与映射complexCalculation(e)在该集合上的结果流相等的结果流。在代码中,这看起来像:
Stream map1 = bigCollection.parallelStream().map(e -> part1(e));
Stream map2 = bigCollection.parallelStream().map(e -> part2(e));
// preferably map1 and map2 are computed concurrently...
Stream result = map1.zip(map2, (e1, e2) -> e1 * e2);

result.equals(bigCollection.map(e -> complexCalculation(e))); //should be true

所以我的问题是:是否存在一些类似于我在这里描述的zip函数的功能?

1
这里讨论了Zip 使用JDK8和lambda压缩流 - sibnick
2个回答

4

parallelStream()保证按照提交的顺序完成。这意味着您不能假设两个parallelStreams可以像这样一起压缩。

除非您的集合实际上比您拥有的CPU数量小,否则您原来的bigCollection.map(e -> complexCalculation(e))可能会更快。


2

如果您真的想要并行化part1part2(例如,您的bigCollection元素很少,小于CPU核心数),则可以使用以下技巧。假设您在当前类中有两种方法part1part2

public long part1(Type t) { ... }
public long part2(Type t) { ... }

创建两个函数并从中创建一个流,然后像这样并行处理它:
bigCollection.parallelStream()
    .map(e -> Stream.<ToLongFunction<Type>>of(this::part1, this::part2)
            .parallel()
            .mapToLong(fn -> fn.applyAsLong(e)).reduce(1, (a, b) -> a*b))
    .// continue the outer stream operations

然而这种情况非常罕见。正如@PeterLawrey所指出的,如果你的外部集合足够大,就不需要并行化part1part2,而是可以并行处理单独的元素。


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