title: Asynchronously populating a Java Map and returning it as a future
body: <p>I've got a map of objects which are expensive to create, and so I want to create the objects and fill the map in parallel with other processes in my application. Only when the main thread actually needs to access the map should the application wait for the asynchronous task(s) populating the map to finish. How can I most elegantly accomplish this?</p>
  
  <h2>Current approach</h2>
  
  <p>Currently, I am able to create each individual object in the map itself asynchronously using <a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html#runAsync-java.lang.Runnable-java.util.concurrent.Executor-" rel="noreferrer"><code>CompletableFuture.runAsync(Runnable, Executor)</code></a> analogously to in the example code below, but I'm unsure of how I can build a <code>Future</code>/<code>CompletableFuture</code>-type mechanism for returning the <code>Map</code> itself when ready:</p>
  
  <pre><code>public static class AsynchronousMapPopulator {
  
      private final Executor backgroundJobExecutor;
  
      public AsynchronousMapPopulator(final Executor backgroundJobExecutor) {
          this.backgroundJobExecutor = backgroundJobExecutor;
      }
  
      public ConcurrentMap&lt;String, Integer&gt; apply(final Map&lt;String,Integer&gt; input) {
          final ConcurrentMap&lt;String, Integer&gt; result = new ConcurrentHashMap&lt;&gt;(input.size());
          final Stream.Builder&lt;CompletableFuture&lt;Void&gt;&gt; incrementingJobs = Stream.builder();
          for (final Entry&lt;String, Integer&gt; entry : input.entrySet()) {
              final String className = entry.getKey();
              final Integer oldValue = entry.getValue();
              final CompletableFuture&lt;Void&gt; incrementingJob = CompletableFuture.runAsync(() -&gt; {
                  result.put(className, oldValue + 1);
              }, backgroundJobExecutor);
              incrementingJobs.add(incrementingJob);
          }
          // TODO: This blocks until the training is done; Instead, return a
          // future to the caller somehow
          CompletableFuture.allOf(incrementingJobs.build().toArray(CompletableFuture[]::new)).join();
          return result;
      }
  }
  </code></pre>
  
  <p>However, with the code above, when code calls <code>AsynchronousTest.create(Map&lt;String,Integer)</code>, it already blocks until the method returns the entirely-populated <code>ConcurrentMap&lt;String,Integer&gt;</code>; How can I turn this into something like a <code>Future&lt;Map&lt;String,Integer&gt;&gt;</code> so that I can use it at a later time?:</p>
  
  <pre><code>Executor someExecutor = ForkJoinPool.commonPool();
  Future&lt;Map&lt;String,Integer&gt;&gt; futureClassModels = new AsynchronousMapPopulator(someExecutor).apply(wordClassObservations);
  ...
  // Do lots of other stuff
  ...
  Map&lt;String,Integer&gt; completedModels = futureClassModels.get();
  </code></pre>