Quick-n-Dirty
Is it possible to refactor a traditional event listener into a Java 8 Stream, such that listener events become the stream source?
Long Story
A client submits an arbitrary job, then listens for results:
Client client = new JobClient()
client.addTaskListener(this)
client.submitJobAsync( new MultiTaskJob())  //returns void, important (see below)
public void onTaskResult(TaskResult result){
  if(result.isLastResult())
    aggregateJobResults(result)
  else
    processResult(result)
}
Problem
For any job submitted, the client receives n results, but it doesn't know how many results it will receive (it uses isLastResult() to determine when to stop and aggregate).
Goal
I want to refactor the listener into a "supplier", or something similiar, such that onTaskResult() is the stream source:
Supplier<TaskResult> taskResultSupplier = 
    () -> Stream.of( .. )   //onTaskResult() feeds this
            .map(result -> {
               if(result.isLastResult())
                 //logic here
             });
Something like that; if I can do it without the client knowing how many results to expect, I'm golden; right now, submitJobAsync() returns void, I'd like to keep it that way, but I'm open to options as well...
Alternatives
After reading up on CompletableFutures by Tomasz Nurkiewicz for a similar scenario, an alternate option exists, assuming a minor change to the client:
List<CompletableFuture<TaskResult>> taskFutures = 
  client.submitJobAsync( new MultiTaskJob())
Here, the client gets a list of CompletableFutures<TaskResult>, so we need to collect the results of the futures when they complete:
//processes all task result futures 
List<TaskResult> = taskFutures.stream()
  .map(taskResult ->
     taskResult.thenApply(this::processResult))
  .collect(Collectors.<TaskResult>toList());
The article also illustrates using CompletableFuture.allOf(..) to perform final processing but only after all futures complete (it's pretty slick); that's where aggregation would occur in my case. No code to show for that here, though the article does a great job explaining it (I'm a total n00b with streams, though if I get it working I'll post the code:-D )