EMZETT.
Login

Java streams (Stream API)

In short: The Stream API (since Java 8) processes data as an “assembly line”: a source such as a list becomes a stream to which you apply steps such as filter, transform and collect. Streams are something different from the I/O streams for files.

In more detail: Instead of loops with intermediate variables you describe what should happen (declarative). A stream stores no data; it is a description of the processing. The work happens only when a terminal operation is called (“lazy”).

In Depth

List<String> names = List.of("Anna", "Ben", "Cem", "Amelie", "Anton");
 
List<String> result = names.stream()               // source
    .filter(n -> n.startsWith("A"))                // intermediate: select
    .map(String::toUpperCase)                      // intermediate: transform
    .sorted()                                      // intermediate: sort
    .collect(Collectors.toList());                 // terminal: collect
// [AMELIE, ANNA, ANTON]
 
int sum = IntStream.rangeClosed(1, 100).sum();      // 5050
double avg = names.stream().mapToInt(String::length).average().orElse(0);
Map<Integer, List<String>> byLength = names.stream().collect(Collectors.groupingBy(String::length));

Structure of a pipeline: source → intermediate operations (return a stream again) → one terminal operation.

KindExamples
Sourcelist.stream(), Arrays.stream(a), Stream.of(...), IntStream.range(...), Files.lines(path)
Intermediatefilter, map, flatMap, sorted, distinct, limit, skip, peek
Terminalcollect, forEach, reduce, count, sum, min, max, anyMatch, findFirst, toList()
  • Lazy: Without a terminal operation nothing happens. limit(3) stops as soon as three hits exist.
  • Usable once: A stream can be processed only once, afterwards IllegalStateException.
  • Original unchanged: Streams do not modify the source. The result is a new collection.
  • Parallel: parallelStream() distributes the work over several cores. Useful only for large amounts and without side effects, otherwise often slower.
  • Primitive streams: IntStream, LongStream, DoubleStream avoid boxing and offer sum(), average().
  • No side effects: Do not modify outside variables inside map and filter.
  • Readability: Long chains become unclear. Then move parts into named methods or use a normal loop.

See also: Lambda, Java: lambdas and streams, Iterate