code: public static <K, V> CompletableFuture<Map<K, V>> allOfWithResults(Map<K, CompletableFuture<V>> futureMap) {
          return Futures
                  .allOf(futureMap.values())
                  .thenApply(ignored ->
                          futureMap.entrySet().stream()
                                   .collect(Collectors.toMap(Map.Entry::getKey, future -> future.getValue().join()))
                  );
      }
docs: Similar to CompletableFuture.allOf(varargs), but that works on a Map and that returns another Map which has the
  results of the given CompletableFutures, with the same input keys.
  
  @param futureMap A Map of Keys to CompletableFutures to wait on.
  @param <K>       The type of the Keys.
  @param <V>       The Type of the Values.
  @return A CompletableFuture that will contain a Map of Keys to Values, where Values are the results of the Futures
  in the input map.