Rico Kahler Rico Kahler - 1 year ago 73
Java Question

What is CompletableFuture's equivalent of flatMap?

I have this weird type

but i want
. Is this possible?

public Future<byte[]> convert(byte[] htmlBytes) {
PhantomPdfMessage htmlMessage = new PhantomPdfMessage();
htmlMessage.setTimestamp(new Date());

CompletableFuture<CompletableFuture<byte[]>> thenApply = CompletableFuture.supplyAsync(this::getPhantom, threadPool).thenApply(
worker -> worker.convert(htmlMessage).thenApply(
pdfMessage -> Base64.getDecoder().decode(pdfMessage.getEncodedContent())


Answer Source

There's a bug in its documentation, but the CompletableFuture#thenCompose family of methods is the equivalent of a flatMap. Its declaration should also give you some clues

public <U> CompletableFuture<U> thenCompose(Function<? super T,? extends CompletionStage<U>> fn)

thenCompose takes the result of the receiver CompletableFuture (call it 1) and passes it to the Function you provide, which must return its own CompletableFuture (call it 2). The CompletableFuture (call it 3) returned by thenCompose will be completed when 2 completes.

In your example

CompletableFuture<Worker> one = CompletableFuture.supplyAsync(this::getPhantom, threadPool);
CompletableFuture<PdfMessage /* whatever */> two = one.thenCompose(worker -> worker.convert(htmlMessage));
CompletableFuture<byte[]> result = two.thenApply(pdfMessage -> Base64.getDecoder().decode(pdfMessage.getEncodedContent()));