问题描述
我看不出这两者之间的主要区别:
List<CompletableFuture<Integer>> intFutures = Stream.of(1,2,3,4)
.map(input -> CompletableFuture.supplyAsync(() -> computeSomethingLong(input)))
.map(future -> future.thenApply(input -> input * 2))
.map(future -> future.thenCompose(computed -> CompletableFuture.supplyAsync(() -> computeSomethingLong(computed))))
.collect(toList());
还有这个:
List<CompletableFuture<Integer>> intFutures = Stream.of(1,4)
.map(input -> CompletableFuture.supplyAsync(() -> computeSomethingLong(input))
.thenApply(computed -> computed * 2)
.thenCompose(computed -> CompletableFuture.supplyAsync(() -> computeSomethingLong(computed))))
.collect(toList());
我做了一个测试,结果和执行时间是一样的。
我能看到的唯一区别是第二个提案允许访问沿链的 input
变量。因此,如果我稍后在另一项任务中需要它,我可以使用它。
我错了吗?还有其他区别吗?
解决方法
你的结论是正确的。 (几乎)没有区别——多次调用 map
可能会分配更多的内存,因为需要创建和返回一个新的流实例。在语义上,这两种形式是等价的并产生相同的结果。
如果您需要访问您输入的初始值,那么您需要将这些操作合并为一个操作;否则该变量在操作(即 lambda)范围内不可用。
更一般地说:
stream
.map(x -> operation1(x))
.map(x -> operation2(x))
.map(x -> operation3(x))
.toList();
// is equivalent to:
stream
.map(x -> operation3(operation2(operation1(x))))
.toList();
或者使用方法调用:
stream
.map(x -> x.method1())
.map(x -> x.method2())
.map(x -> x.method3())
.toList();
// equivalent to:
stream
.map(x -> x.method1().method2().method3())
.toList();