Intermediate vs Terminal Operations in Java Stream API

1. Introduction

In Java's Stream API, operations are categorized into intermediate and terminal operations. Intermediate operations return a new stream and are always lazy, meaning they don't start processing the content until a terminal operation is invoked. Terminal operations, on the other hand, are eager and once invoked, they process the stream and produce a result or a side-effect.

2. Key Points

1. Intermediate operations are lazy and can be chained to form a pipeline, which does not execute until a terminal operation is invoked.

2. Terminal operations are eager and trigger the processing of data, concluding the stream pipeline.

3. Intermediate operations transform a stream into another stream (e.g., filter, map).

4. Terminal operations produce a result (e.g., a list, a count, or simply void in the case of forEach).

3. Differences

Intermediate Operations Terminal Operations
Do not start processing the elements. Trigger the processing of elements.
Always return a new stream. Return a non-stream result or produce a side-effect.
Examples include map, filter, sorted. Examples include collect, forEach, reduce.

4. Example


public class StreamOperationsExample {
    public static void main(String[] args) {
        // Intermediate operation (filter) followed by a terminal operation (forEach)
        Stream.of("apple", "banana", "cherry", "date")
            .filter(fruit -> fruit.startsWith("b")) // Intermediate operation
            .forEach(System.out::println);           // Terminal operation




1. filter is an intermediate operation that sets up a condition but does not start processing.

2. forEach is a terminal operation that starts the processing of filtered elements and performs an action on each of them.

5. When to use?

- Use intermediate operations to set up a pipeline of operations that you want to perform on the data.

- Use terminal operations when you're ready to initiate the processing and produce a result.