Fundamentals 9 min read

Introduction to Java 8 Stream API: Creation, Intermediate and Terminal Operations

This article introduces Java 8’s Stream API, explaining its purpose, key characteristics, how to create streams from collections or directly, and demonstrating common intermediate operations such as filter, map, limit, sorted, distinct, as well as terminal operations like forEach, count, and collect, with code examples.

Full-Stack Internet Architecture
Full-Stack Internet Architecture
Full-Stack Internet Architecture
Introduction to Java 8 Stream API: Creation, Intermediate and Terminal Operations

In Java, collections and arrays are frequently used, but before Java 8 manipulating them required verbose code. Java 8 added the Stream API, a declarative abstraction that lets developers process data in a way similar to SQL queries.

Streams provide several advantages: they have no storage of their own, are designed for functional programming, execute lazily (operations run only when a result is needed), and can be consumed only once, mirroring the behavior of iterators.

Streams can be created in two main ways. First, any existing collection can produce a stream via the stream() (or parallelStream() ) method. Second, a stream can be built directly with Stream.of(...) . Example:

List
strings = Arrays.asList("Hollis", "HollisChuang", "hollis", "Hello", "HelloWorld", "Hollis");
Stream
stream = strings.stream();

Stream
stream2 = Stream.of("Hollis", "HollisChuang", "hollis", "Hello", "HelloWorld", "Hollis");

Common intermediate operations include filter , map , limit/skip , sorted and distinct . Each operation returns another stream, allowing them to be chained. Examples:

List
strings = Arrays.asList("Hollis", "", "HollisChuang", "H", "hollis");
strings.stream().filter(s -> !s.isEmpty()).forEach(System.out::println);

List
numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
numbers.stream().map(i -> i * i).forEach(System.out::println);

numbers.stream().limit(4).forEach(System.out::println);

numbers.stream().sorted().forEach(System.out::println);

numbers.stream().distinct().forEach(System.out::println);

A typical pipeline might combine several intermediate steps before a terminal operation:

List
strings = Arrays.asList("Hollis", "HollisChuang", "hollis", "Hello", "HelloWorld", "Hollis");
Stream s = strings.stream()
    .filter(str -> str.length() <= 6)
    .map(String::length)
    .sorted()
    .limit(3)
    .distinct();

Terminal operations produce a final result and consume the stream. Frequently used terminals are forEach , count and collect . After a terminal operation the stream cannot be reused.

Random random = new Random();
random.ints().limit(10).forEach(System.out::println);

List
strings = Arrays.asList("Hollis","HollisChuang","hollis","Hollis666","Hello","HelloWorld","Hollis");
System.out.println(strings.stream().count());

strings = strings.stream()
    .filter(s -> s.startsWith("Hollis"))
    .collect(Collectors.toList());
System.out.println(strings);

Overall, the Stream API offers a concise, functional style for processing collections, improving readability and productivity. This article covered how to create streams, the most useful intermediate operations, and the essential terminal operations.

JavaFunctional ProgrammingCollectionsStream APIJava 8Intermediate OperationsTerminal Operations
Full-Stack Internet Architecture
Written by

Full-Stack Internet Architecture

Introducing full-stack Internet architecture technologies centered on Java

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.