有没有办法压缩两个流?

时间:2015-08-21 09:10:03

标签: java concurrency java-8 java-stream

这个问题源自another question的答案,其中建议使用map和reduce来同时计算总和。

在那个问题中有一个complexCalculation(e),但现在我想知道如何通过将计算分成两部分来进行更多的并行化,以便complexCalculation(e) = part1(e) * {{1 }}。我想知道是否有可能同时计算集合上的part1和part2(再次使用part2(e))然后压缩两个结果流,以便两个流的第i个元素与函数*组合,以便得到stream等于可以通过在该集合上映射map()获得的流。在代码中,这看起来像:

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 函数?

2 个答案:

答案 0 :(得分:4)

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

您的原始bigCollection.map(e -> complexCalculation(e))可能会更快,除非您的收藏实际上小于您拥有的CPU数量。

答案 1 :(得分:2)

如果你真的想并行化part2part1(例如你的bigCollection只有很少的元素,少于CPU内核),你可以做以下技巧。假设您在当前类中有两个方法part2public 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

创建一个由这些方法创建的两个函数的流,并按照以下方式并行处理:

part1

然而,这是非常罕见的情况。正如@PeterLawrey指出,如果您的外部集合足够大,则无需并行化part2[[GNTextFieldsCollectionManager alloc] initWithView:self.view]; 。相反,您将并行处理单独的元素。