JavaStream Operations

Stream Operations

Stream operations fall into two categories: intermediate operations, which transform a stream into another stream and are lazy, and terminal operations, which consume the stream and actually produce a result. Building a useful pipeline usually means chaining a few intermediate operations and finishing with exactly one terminal operation.

Intermediate operations

Each of these returns a new stream, so they can be chained together fluently. None of them run any actual work until a terminal operation is called.

Operation

What it does

.filter(Predicate)

Keeps only elements matching the predicate

.map(Function)

Transforms each element into a new value

.sorted() / .sorted(Comparator)

Sorts elements by natural order or a given comparator

.distinct()

Removes duplicate elements (using equals())

.limit(n)

Truncates the stream to at most n elements

.skip(n)

Discards the first n elements

Terminal operations

A terminal operation triggers the entire pipeline to actually run and produces a concrete result — a collection, a value, or nothing at all in the case of .forEach(). After a terminal operation runs, the stream is consumed and cannot be reused.

Operation

What it does

.collect(Collector)

Gathers elements into a List, Set, Map, or other structure

.forEach(Consumer)

Performs an action on each element

.count()

Returns the number of elements as a long

.reduce(BinaryOperator)

Combines all elements into a single value

.anyMatch() / .allMatch() / .noneMatch()

Short-circuiting boolean checks against a predicate

.findFirst()

Returns an Optional with the first element, if present

A full worked example

The example below chains several intermediate operations — filtering, mapping, and sorting — before finishing with a .collect() terminal operation.

Filter, map, sort, and collect

Java
record Employee(String name, String department, double salary) {}

List<Employee> employees = List.of(
    new Employee("Alice", "Engineering", 95000),
    new Employee("Bob", "Sales", 62000),
    new Employee("Charlie", "Engineering", 110000),
    new Employee("Dave", "Sales", 58000)
);

List<String> topEngineerNames = employees.stream()
    .filter(e -> e.department().equals("Engineering"))   // keep only Engineering
    .filter(e -> e.salary() > 90000)                       // keep high earners
    .map(Employee::name)                                    // Employee -> String
    .sorted()                                               // alphabetical order
    .collect(Collectors.toList());                          // gather into a List

System.out.println(topEngineerNames);   // [Alice, Charlie]

Each .filter() and .map() call returns a new stream, so they read top-to-bottom as a sequence of transformation steps, and only .collect() at the end actually executes the pipeline and produces the result.

A few terminal operations in isolation

Java
List<Integer> numbers = List.of(4, 9, 15, 20, 2, 8);

long countAboveTen = numbers.stream().filter(n -> n > 10).count();     // 2

boolean anyNegative = numbers.stream().anyMatch(n -> n < 0);            // false

Optional<Integer> firstEven = numbers.stream().filter(n -> n % 2 == 0).findFirst();
System.out.println(firstEven.get());                                    // 4

int sum = numbers.stream().reduce(0, Integer::sum);                     // 58
Note
`.collect()` almost always takes a `Collector` produced by a static factory method on the `Collectors` utility class — `Collectors.toList()`, `Collectors.joining()`, `Collectors.groupingBy()`, and more. The dedicated **Collectors** page covers the full set with a worked `groupingBy` example.
  • Intermediate operations (filter, map, sorted, distinct, limit, skip) return a new stream and can be chained.

  • Terminal operations (collect, forEach, count, reduce, the *Match methods, findFirst) trigger execution and consume the stream.

  • A pipeline typically chains several intermediate operations and ends in exactly one terminal operation.

  • .collect() is the most common terminal operation, usually paired with a factory method from Collectors.