Why is CompletableFuture.allOf declared as CompletableFuture<Void>?

anyOf has to somehow tell you what was the result of the specific CompletableFuture whose completion triggered anyOf. That's not necessary in case of allOf because you know which futures completed -- all of them.

allOf (just as anyOf) doesn't require that all futures bear the same type. So if it were to return a future of collection, it would have to be a collection of Object which is probably not what you want anyway.

If you really want to have allOf return a future of collection, it's fairly straightforward to write your own:

public static CompletableFuture<List<Object>> myAllOf(CompletableFuture<?>... futures) {
     return CompletableFuture.allOf(futures)
            .thenApply(x -> Arrays.stream(futures)
                    .map(f -> (Object) f.join())
                    .collect(toList())
            );
}

If you have a type-safe version of this problem and need to convert a collection of futures of a certain type to a future of collection of that same type, see this question for several examples: List<Future> to Future<List> sequence