Java Stream API Tutorial: Definitions, Operations, and Code Examples
This tutorial provides a comprehensive overview of Java's Stream API, explaining its definition, how to obtain streams, the structure of stream processing, and detailed examples of common intermediate and terminal operations with complete code snippets.
This article is a detailed tutorial on Java's Stream API, covering its definition, how to obtain streams, the composition of stream processing, and a thorough list of common intermediate and terminal operations with code examples.
Definition of Stream
In Java, a Stream is a component that can internally iterate over its elements, meaning the Stream handles the iteration itself. This differs from using a Collection's iterator or the Iterable interface's forEach method, where the developer must manage iteration.
Stream Processing
Processor methods (or listeners) can be attached to a Stream. When the Stream iterates internally, each element is passed to these processors, which are invoked for every element, forming a processing chain.
Multiple processor methods can be chained: the output of one processor becomes the input for the next. Processors may return the same element or a transformed one, depending on their purpose.
How to Obtain a Stream
The most common way to get a Stream is from a Collection. Example:
List<String> items = new ArrayList<>();
items.add("one");
items.add("two");
items.add("three");
Stream<String> stream = items.stream();All collection objects implement the Collection interface, which defines the stream() method.
Composition of Stream Processing
A Stream processing pipeline consists of a source, zero or more intermediate operations, and a terminal operation.
Source: the origin of elements, such as a Collection.
Intermediate operations: added processors that return a new Stream; they are lazily executed.
Terminal operation: triggers internal iteration, applies all processors, and returns a result.
Intermediate Operations
map
map()transforms each element to another object, e.g., converting strings to uppercase.
List<String> list = new ArrayList<>();
Stream<String> stream = list.stream();
Stream<String> streamMapped = stream.map(value -> value.toUpperCase());filter
filter()removes elements that do not satisfy a given Predicate.
Stream<String> longStringsStream = stream.filter(value -> value.length() >= 3);flatMap
flatMap()maps each element to a Stream and then flattens the resulting Streams into a single Stream.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class StreamFlatMapExamples {
public static void main(String[] args) {
List<String> stringList = new ArrayList<>();
stringList.add("One flew over the cuckoo's nest");
stringList.add("To kill a mockingbird");
stringList.add("Gone with the wind");
Stream<String> stream = stringList.stream();
stream.flatMap(value -> {
String[] split = value.split(" ");
return Arrays.asList(split).stream();
}).forEach(value -> System.out.println(value));
}
}distinct
distinct()returns a new Stream containing only unique elements, removing duplicates.
List<String> stringList = new ArrayList<>();
stringList.add("one");
stringList.add("two");
stringList.add("three");
stringList.add("one");
Stream<String> stream = stringList.stream();
List<String> distinctStrings = stream.distinct().collect(Collectors.toList());
System.out.println(distinctStrings); // [one, two, three]limit
limit(n)truncates the Stream to contain at most n elements.
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
public class StreamLimitExample {
public static void main(String[] args) {
List<String> stringList = new ArrayList<>();
stringList.add("one");
stringList.add("two");
stringList.add("three");
stringList.add("one");
Stream<String> stream = stringList.stream();
stream.limit(2).forEach(element -> System.out.println(element));
}
}peek
peek()is a debugging intermediate operation that consumes each element with a Consumer without modifying the Stream.
Stream.of("one", "two", "three", "four")
.filter(e -> e.length() > 3)
.peek(e -> System.out.println("Filtered value: " + e))
.map(String::toUpperCase)
.peek(e -> System.out.println("Mapped value: " + e))
.collect(Collectors.toList());Terminal Operations
Terminal operations start internal iteration and produce a final result.
anyMatch
anyMatch(predicate)returns true if any element satisfies the predicate.
boolean anyMatch = stream.anyMatch(value -> value.startsWith("One"));
System.out.println(anyMatch);allMatch
allMatch(predicate)returns true only if all elements satisfy the predicate.
boolean allMatch = stream.allMatch(value -> value.startsWith("One"));
System.out.println(allMatch);noneMatch
noneMatch(predicate)returns true if no elements satisfy the predicate.
boolean noneMatch = stream.noneMatch(element -> "xyz".equals(element));
System.out.println("noneMatch = " + noneMatch);collect
collect()gathers the Stream's elements into a collection or another container.
List<String> stringsAsUppercaseList = stream
.map(value -> value.toUpperCase())
.collect(Collectors.toList());
System.out.println(stringsAsUppercaseList);count
count()returns the number of elements in the Stream.
long count = stream.flatMap(value -> {
String[] split = value.split(" ");
return Arrays.asList(split).stream();
}).count();
System.out.println("count = " + count);findAny
findAny()returns an Optional containing any element of the Stream.
Optional<String> anyElement = stream.findAny();
if (anyElement.isPresent()) {
System.out.println(anyElement.get());
} else {
System.out.println("not found");
}findFirst
findFirst()returns an Optional containing the first element of the Stream.
Optional<String> firstElement = stream.findFirst();
if (firstElement.isPresent()) {
System.out.println(firstElement.get());
} else {
System.out.println("not found");
}forEach
forEach()performs an action for each element; it returns void.
stream.forEach(System.out::println);min / max
min(comparator)and max(comparator) return the smallest or largest element according to the provided Comparator, wrapped in an Optional.
Optional<String> min = stream.min(String::compareTo);
Optional<String> max = stream.max(String::compareTo);reduce
reduce()aggregates Stream elements into a single result using a binary operator.
Optional<String> reduced = stream.reduce((value, combined) -> combined + " + " + value);
reduced.ifPresent(System.out::println);toArray
toArray()converts the Stream into an array of Object, with an overloaded version allowing a typed array.
Object[] objects = stream.toArray();
String[] strArray = stream.toArray(String[]::new);Stream Concatenation
The static method Stream.concat(stream1, stream2) merges two Streams into one.
Stream<String> concatStream = Stream.concat(stream1, stream2);
List<String> combined = concatStream.collect(Collectors.toList());
System.out.println(combined);Creating Streams from Arrays
The static method Stream.of(...) can create a Stream from individual objects, multiple objects, or an array.
Stream<String> stream1 = Stream.of("one", "two", "three");
Stream<String> stream2 = Stream.of(new String[]{"one", "two"});
System.out.println(stream1.count()); // 3
System.out.println(stream2.count()); // 2In summary, this article enumerates the main intermediate and terminal operations of Java Streams, providing simple examples to illustrate their effects. A follow‑up article will demonstrate more complex, high‑frequency Stream usages in real projects.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
