santosh jk
santosh jk

Reputation: 171

How Can I skip futures which are completing exceptionally

Below code snippet to consolidate completable future . the problem with below is some of my futures are completing exceptionally so on a whole my result is completeling exceptionally .

from the java doc I understand allof returns exception when any future throws exception "Returns a new CompletableFuture that is completed when all of the given CompletableFutures complete. If any of the given CompletableFutures complete exceptionally, then the returned CompletableFuture also does so, with a CompletionException holding this exception as its cause."

but I dont see any other api that helps me to get future when all are done

can some one help me or any clues How Can I skip futures which are completing exceptionally . In other words I want to get futures which are completed without exceptions .

CompletableFuture<List<Pair<ExtensionVO, GetObjectResponse>>> result =
          CompletableFuture.allOf(
                  completableFutures.toArray(new CompletableFuture<?>[completableFutures.size()]))
              .thenApply(
                  v ->
                      completableFutures
                          .stream()
                          .map(CompletableFuture::join)
                          .filter(Objects::nonNull) 
                          .collect(Collectors.toList()));

Upvotes: 0

Views: 1638

Answers (1)

Holger
Holger

Reputation: 298499

First, you have to use handle to chain a function which can produce a result even in the exceptional case, then, use .filter(f -> !f.isCompletedExceptionally()) to skip exceptionally completed futures before calling join():

CompletableFuture<List<Pair<ExtensionVO, GetObjectResponse>>> result =
    CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture<?>[0]))
        .handle((voidResult,throwable) ->
            completableFutures
                    .stream()
                    .filter(f -> !f.isCompletedExceptionally())
                    .map(CompletableFuture::join)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList()));

In principle, you could use the throwable to determine whether an exception happened, to perform the isCompletedExceptionally() check only when necessary:

CompletableFuture<List<Pair<ExtensionVO, GetObjectResponse>>> result =
    CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture<?>[0]))
        .handle((voidResult, throwable) ->
            (throwable == null?
                completableFutures.stream():
                completableFutures.stream().filter(f -> !f.isCompletedExceptionally()))
            .map(CompletableFuture::join)
            .filter(Objects::nonNull)
            .collect(Collectors.toList()));

but this may only pay off for really large lists, if ever.

Upvotes: 1

Related Questions