When you want to Concatenate the list of CompletableFuture<T>
, CompletableFuture#allOf
is really inconvenient because the result type of the method is unfortunately CompletableFuture<Void>
.
CompletableFuture<List<GitHubStar>> f1 = findStars("aaa");
CompletableFuture<List<GitHubStar>> f2 = findStars("bbb");
CompletableFuture<List<GitHubStar>> f3 = findStars("ccc");
CompletableFuture<Void> result = CompletableFuture.allOf(f1, f2, f3); // Void...! I want to merge the results :S
Instead of allOf
, thenCombine
is useful.
CompletableFuture<List<GitHubStar>> f1 = findStars("aaa");
CompletableFuture<List<GitHubStar>> f2 = findStars("bbb");
CompletableFuture<List<GitHubStar>> result = f1.thenCombine(f2, (l1, l2) -> {
l1.addAll(l2);
return l1;
});
But how about combining List<CompletableFuture<List<GitHubStar>>>
?
You can use Stream#reduce
.
Optional<CompletableFuture<List<GitHubStar>>> ret = usernames.stream()
.map(main::findStars)
.reduce((f1, f2) -> f1.thenCombine(f2, (l1, l2) -> {
l1.addAll(l2);
return l1;
}));
ret.get().thenAccept(stars -> stars.stream()
.distinct()
.sorted(Comparator.comparing(GitHubStar::getUpdatedAt).reversed())
.forEach(System.out::println)
).get();
Sample code is here.