One of the main benefits of using streams is that it gives the ability to process data in a declarative way, that is, using a functional style of programming. It also gives multi-threading capability for free meaning there is no need to write any extra multi-threaded code to make your stream concurrent.
Assuming the reason you are exploring this style of programming is that you want to exploit these benefits then your first code sample is potentially not functional since the foreach
method is classed as being terminal (meaning that it can produce side-effects).
The second way is preferred from functional programming point of view since the map function can accept stateless lambda functions. More explicitly, the lambda passed to the map function should be
- Non-interfering, meaning that the function should not alter the source of the stream if it is non-concurrent (e.g.
ArrayList
). - Stateless to avoid unexpected results when doing parallel processing (caused by thread scheduling differences).
Another benefit with the second approach is if the stream is parallel and the collector is concurrent and unordered itthen these characteristics can provide useful hints to the reduction operation to do the collecting concurrently.