How Java works

Pick a topic, write code and watch what happens inside, step by step.

Memory

Collections

Concurrency

Language and JVM

Topics

How Stream works

Streams are lazy

filter and map do no work: they only build the pipeline. Without a terminal operation, no lambda runs.

Pick a terminal on the left, such as toList. Then Next starts working.

Elements pass one by one

Many people think all elements go through filter, then all through map. They do not.

Each element goes through the whole pipeline before the next one starts, which avoids needless work.

Change the list and the operations on the left: the result is computed live.

Short-circuit

findFirst, anyMatch and limit can end the work early. Once the result is found, the remaining elements are never read.

There are 6 elements here, but only 2 are processed. This is also why infinite streams work: Stream.iterate(...).limit(5).

sorted holds them all

sorted is a stateful operation: it must see every element to sort. So elements pile up in front of it.

A later limit(2) saves nothing, as everything is read from the source. Where you can, put filter before sorted.

distinct also remembers every value it saw, but it lets elements through at once.

count sometimes runs nothing

Here the map lambda does not run even once. Since JDK 9, when the size is known, count does not visit the elements.

Add a filter: the size is no longer known and the lambda runs. Try it on the left.

Trap: do not rely on side effects in peek or map, because they may not run.

A lambda is an object

A lambda is an object of a functional interface. The values it captures are copied into that object, so a local variable must be effectively final.

A non-capturing lambda usually stays one object, while a capturing one may create a new object each time.

A stream is single-use: it cannot run again after its terminal.