Terminal Operations
A terminal operation starts the pipeline
As long as a chain contains only intermediate operations, it merely describes future work. A terminal operation starts the processing and finishes the stream. After that, the same stream cannot be reused.
Get a collection, a count, or perform an action
toList() collects elements into a list,
count() returns their number,
and forEach() performs an action for the elements.
List<String> names = List.of("Ann", "Bob", "Alexander");
long count = names.stream()
.filter(name -> name.length() > 3)
.count();
The value of count is 1.
If a list is needed instead, the same chain can end with toList().
Checks and searches can finish early
anyMatch, allMatch, and noneMatch
check elements against a condition. findFirst and findAny
search for an element. These operations do not have to traverse the entire stream when the answer is already known.
boolean hasLongName = names.stream()
.anyMatch(name -> name.length() > 8);
As soon as a matching string is found, further traversal may be unnecessary.
A search result is returned through Optional
because a matching element may not exist. We will examine Optional itself later in this section.
min, max, and reduce fold elements
min and max find an extreme element according to a Comparator.
reduce repeatedly combines elements into one result.
int sum = Stream.of(3, 5, 7)
.reduce(0, Integer::sum);
The initial value here is 0,
and each next element is added to the accumulated result.
For numeric sums, we will later see more direct operations on primitive streams,
but reduce shows the general idea of reduction.