What matters the most in Java 8 – Part 2 – Stream


A java.util.Stream represents a sequence of elements on which one or more operations can be performed.

  • Stream operations are either intermediate or terminal. While terminal operations return a result of a certain type, intermediate operations return the stream itself so you can chain multiple method calls in a row.
  • Streams are created on a source, e.g. a java.util.Collection like lists or sets (maps are not supported).
  • Stream is like the existing “streams” (e.g. InputStream), you can consume streams only once.
  • Stream operations can either be executed sequential or parallel.
  • Parallel streams use the common ForkJoinPool for threading and it has 2 caveats:
    • The size of the pool = logical cores – 1 (good for cpu intensive tasks but not IO bound tasks)
    • It is global pool shared by all

Key concepts

  • Pipelining: Many stream operations return a stream themselves. This allows operations to be chained to form a larger pipeline. This enables certain optimizations, such as laziness and short-circuiting. For laziness, no work is actually done until terminal operation is invoked.
  • Internal iteration: In contrast to collections, which are iterated explicitly (external iteration), stream operations do the iteration behind the scenes for you.
    • Focus on computation – Collections are about data and streams are about computations. And stream doesn’t own any data.

Key Stream Operations

  • Intermediate operations return stream that allows you to chain up and lazily executed.
    • filter – to filter out elements not matching the predicate
    • map – to transform to another type but can be the same type
    • flatMap – to flatten out list of list to a single list.
    • peek
    • distinct, sorted, limit – Those are special kind of intermediate operation. It’s a so called stateful operation. For example, to sort a collection of elements, you have to maintain state during ordering.
  • Terminal operations return concrete types or produce a side effect and eagerly executed.
    • collect – to group elements (groupingBy etc)
    • reduce – to cumulate elements
    • forEach – to perform a side effect on elements
    • findFirst – it will short circuit once an element identified
    • anyMatch – boolean
    • allMatch – boolean
    • noneMatch – boolean
    • count, min, max and etc

Source of Stream

Code Examples

Use Stream for in-memory database jobs

Exception Handling

If you don’t want the exceptions to bubble out and interrupt the control flow of the stream, you’ll have to catch them locally.

Parallelism Underneath the Hood

With the Fork/Join framework added in Java SE 7, the JDK has an API for efficiently implementing parallel computations. However, parallel code with Fork/Join looks very different from (and much bigger than) the equivalent serial code, which acts as a barrier to parallelization. By supporting the exact same set of operations on sequential and parallel streams, users can switch between serial and parallel execution without rewriting their code, removing this barrier and making parallelism more accessible and less error-prone. However, all streams use the same ForkJoinPool and so one stream could hold up the resources of others and you need to be careful on that if you try to switch from sequential stream to parallel stream.


What matters the most in Java 8 – Part 2 – Stream

log in

Use demo/demo public access

reset password

Back to
log in
Choose A Format
Personality quiz
Trivia quiz