目前,要使用 Collections of CompletionStage 做一些简单的事情需要跳过几个难看的箍:
public static CompletionStage<String> translate(String foo) {
// just example code to reproduce
return CompletableFuture.completedFuture("translated " + foo);
}
public static CompletionStage<List<String>> translateAllAsync(List<String> input) {
List<CompletableFuture<String>> tFutures = input.stream()
.map(s -> translate(s)
.toCompletableFuture())
.collect(Collectors.toList()); // cannot use toArray because of generics Arrays creation :-(
return CompletableFuture.allOf(tFutures.toArray(new CompletableFuture<?>[0])) // not using size() on purpose, see comments
.thenApply(nil -> tFutures.stream()
.map(f -> f.join())
.map(s -> s.toUpperCase())
.collect(Collectors.toList()));
}
我想写的是:
public CompletionStage<List<String>> translateAllAsync(List<String> input) {
// allOf takes a collection< futures<X>>,
// and returns a future<collection<x>> for thenApply()
return XXXUtil.allOf(input.stream()
.map(s -> translate(s))
.collect(Collectors.toList()))
.thenApply(translations -> translations.stream()
.map(s -> s.toUpperCase())
.collect(Collectors.toList()));
}
关于 toCompletableFuture 并转换为 Array 和 join 的整个过程是样板文件,分散了实际代码语义的注意力。
在某些情况下,可能有一个版本的 allOf() 返回 aFuture<Collection<Future<X>>>
而不是Future<Collection<X>>
也可能有用。
我可以尝试自己实现 XXXUtil,但我想知道是否已经有一个成熟的 3rdparty 库来解决这个问题和类似问题(例如 Spotify 的 CompletableFutures)。如果是这样,我希望看到这样一个库的等效代码作为答案。
或者也许上面发布的原始代码可以以不同的方式以某种方式更紧凑地编写?
JUnit测试代码:
@Test
public void testTranslate() throws Exception {
List<String> list = translateAllAsync(Arrays.asList("foo", "bar")).toCompletableFuture().get();
Collections.sort(list);
assertEquals(list,
Arrays.asList("TRANSLATED BAR", "TRANSLATED FOO"));
}