Appendix C. Performing multiple operations in parallel on a stream
One of the biggest limitations of a Java 8 stream is that you can operate on it only once and get only one result while processing it. Indeed, if you try to traverse a stream for a second time, the only thing you can achieve is an exception like this:
Despite this, there are situations where you’d like to get several results when processing a single stream. For instance, you may want to parse a log file in a stream, as we did in section 5.7.3, but gather multiple statistics in a single step. Or, keeping with the menu data model used to explain Stream’s features in chapters 4–6, you may want to retrieve different information while traversing the stream of dishes.
In other words, you’d like to push a stream through more than one lambda on a single pass, and to do this you need a type of fork method and to apply different functions to each forked stream. Even better, it would be great if you could perform those operations in parallel, using different threads to calculate the different required results.
Unfortunately, these features aren’t currently available on the stream implementation provided in Java 8, but in this appendix we’ll show you a way to use a Spliterator and in particular its late-binding capacity, together with BlockingQueues and Futures, to implement this useful feature and make it available with a convenient API.[1]