CompletedFuture: how to apply a function to a set of CompletingFutures?
Suppose I have 3 downloads framed as terminating futures:
CompletableFuture<Doc> dl1 = CompletableFuture.supplyAsync(() -> download("file1")); CompletableFuture<Doc> dl2 = CompletableFuture.supplyAsync(() -> download("file2")); CompletableFuture<Doc> dl3 = CompletableFuture.supplyAsync(() -> download("file3"));
Then they should all be handled the same way.
CompletableFuture<String> s1 = dl1.thenApply(Doc::getFilename); CompletableFuture<String> s2 = dl2.thenApply(Doc::getFilename); CompletableFuture<String> s3 = dl3.thenApply(Doc::getFilename);
And you can imagine several functions to be applied, all in parallel.
According to the DRY principle, this example seems out of place. So I am looking for a solution to define only 1 workflow that runs 3 times, in parallel.
How can I do that?
it but it has two problems: 1) it starts blocking and 2) the return type can only handle
, not handle it.
source to share
Stream.of("file1", "file2", "file3") // or your input in any other format, that can easily be transformed to a stream... // .parallel() // well... depends... .map(s -> CompletableFuture.supplyAsync(() -> download(s))) .map(dl -> dl.thenApply(Doc::getFilename)) .map(CompletableFuture::join) // if you want to have all the results collected .collect(Collectors.toList());
Of course, you can also combine two characters
. But at least you don't write just x times ... If you don't like the collection
, you can also name something else on it, for example.
has the advantage that as soon as a response is available, the consumer is called.
Or classic: just use a loop and a list / array for input, but you might have to take care of more than you would with streams
source to share