This Java tutorial helps you discover the folllowing terminal operations provided by Java Stream API in details:

1. The allMatch() operation
2. The anyMatch() operation
3. The noneMatch() operation
4. The collect() operation
5. The count() operation
6. The forEach() operation
7. The min() operation
8. The max() operation
9. The reduce() operation

Remember the following two key characteristics of terminal operations:

  • They can return a primitive value (booleanor long), a concrete type (Optional value object), or void (creating side effect).
  • They are eagerly executed, and a terminal operation is always the last operation in a Stream pipeline.
Note that the following examples are still based on the sample data (a list of Person objects) in the tutorial Java Stream Aggregate Functions.

 

1. Java Stream allMatch operation example

The allMatch()operation answers the question: Do all elements in the stream meet this condition? It returns true if and only if all elements match a provided predicate, otherwise return false.

This is a short-circuiting terminal operation because the operation stops immediately if any unmatched element is found (just like short-circuit behavior of the AND operator).

The following example checks if all persons are male:

boolean areAllMale = listPersons.stream()
				.allMatch(p -> p.getGender().equals(Gender.MALE));

System.out.println("Are all persons male? " + areAllMale);
Result:

Are all persons male? false
The following example check if all people using GMail:

boolean useGMail = listPersons.stream()
				.allMatch(p -> p.getEmail().endsWith("gmail.com"));

System.out.println("Does everyone use GMail? " + useGMail);


Result:

Does everyone use GMail? true
Note that if the stream is empty, the method returns true and the predicate is not evaluated.

 

2. Java Stream anyMatch operation example

The anyMatch() operation returns true if any element in the stream matches a provided predicate. In other words, it answers the following question: Is there any element that meets this condition?

The following example checks whether the list has any female:

boolean anyFemale = listPersons.stream()
			.anyMatch(p -> p.getGender().equals(Gender.FEMALE));

System.out.println("Is there any female? " + anyFemale);
Result:

Is there any female? true
The following example checks whether the list has any teenager (age under 20):

boolean anyTeenager = listPersons.stream()
			.anyMatch(p -> p.getAge() < 20);

System.out.println("Is there any teenager? " + anyTeenager);
Output:

Is there any teenager? false
 

3. Java Stream noneMatch operation example

In contrast to the allMatch() operation, the noneMatch() operation returns true if no elements in the stream match a provided predicate. In other words, it answers the question: Does no element meet this condition?

The following example checks if no one uses Yahoo email:

boolean noYahooMail = listPersons.stream()
			.noneMatch(p -> p.getEmail().endsWith("yahoo.com"));

System.out.println("No one uses Yahoo mail? " + noYahooMail);
Result:

No one uses Yahoo mail? true
The following example answers the question: Does anyone come from the Hill family?

boolean noHill = listPersons.stream()
			.noneMatch(p -> p.getLastName().equals("Hill"));

System.out.println("No one comes from Hill family? " + noHill);
Output:

No one comes from Hill family? false
 

4. Java Stream collect operation example

The collect() operation accumulates elements in a stream into a container such as a collection. It performs mutable reduction operation in which the reduced (final) value is a mutable result container such as an ArrayList. This method takes a Collector implementation that provides useful reduction operations. The Collectors class is a common implementation in the JDK. And we are going to see how it is used in the following examples.

The following example accumulates emails of the persons into a list collection:

List<String> listEmails = listPersons.stream()
				.map(p -> p.getEmail())
				.collect(Collectors.toList());

System.out.println("List of Emails: " + listEmails);
Output:

List of Emails: [alice@gmail.com, bob@gmail.com, carol@gmail.com, david@gmail.com, eric@gmail.com, frank@gmail.com, gibb@gmail.com, henry@gmail.com, isabell@gmail.com, jane@gmail.com]
We can specify exactly which type of collection as the result. For example, the following code collects emails into a TreeSet:

Set<String> setEmails = listPersons.stream()
				.map(p -> p.getEmail())
				.collect(Collectors.toCollection(TreeSet::new));
Output:

Set of Emails: [alice@gmail.com, bob@gmail.com, carol@gmail.com, david@gmail.com, eric@gmail.com, frank@gmail.com, gibb@gmail.com, henry@gmail.com, isabell@gmail.com, jane@gmail.com]
The following example groups the person by gender:

Map<Gender, List<Person>> byGender = listPersons.stream()
			.collect(Collectors.groupingBy(p -> p.getGender()));

System.out.println("Groups by gender:\n" + byGender);
Output:

{FEMALE=[Alice Brown, Carol Hill, Isabell Hill, Jane Smith], MALE=[Bob Young, David Green, Eric Young, Frank Thompson, Gibb Brown, Henry Baker]}
 

The following example accumulates first names and concatenates them into a String, separated by commas:

String firstNames = listPersons.stream()
			.map(p -> p.getFirstName())
			.collect(Collectors.joining(", "));
Result:

First Names: Alice, Bob, Carol, David, Eric, Frank, Gibb, Henry, Isabell, Jane
Consult the Collectors Javadoc for more useful mutable reduction operations.

 

5. Java Stream count operation examples

The count() operation simply returns total number of elements in the stream. The following example finds how many people are male:

long totalMale = listPersons.stream()
			.filter(p -> p.getGender().equals(Gender.MALE))
			.count();
System.out.println("Total male: " + totalMale);
Output:

Total male: 6
You can read Java 8 in Action book to learn more in-depth about Java Stream.

 

6. Java Stream forEach operation example

The forEach() operation performs an action for each element in the stream, thus creating a side effect, such as print out information of each female person as shown in the following example:

System.out.println("People are female:");

listPersons.stream()
	.filter(p -> p.getGender().equals(Gender.FEMALE))
	.forEach(System.out::println);
Output:

People are female:
Alice Brown
Carol Hill
Isabell Hill
Jane Smith
 

7. Java Stream min operation example

The min(comparator) is a special reduction operation that returns the minimum element in the stream according to the provided comparator. It returns an Optional which is a container object that contains the value.

For example, the following code snippet finds the youngest female person in the list:

Optional<Person> min = listPersons.stream()
			.filter(p -> p.getGender().equals(Gender.FEMALE))
			.min((p1, p2) -> p1.getAge() - p2.getAge());
if (min.isPresent()) {
	Person youngestGirl = min.get();
	System.out.println("The youngest girl is: "
				+ youngestGirl + " (" + youngestGirl.getAge() + ")");
}
Output:

The youngest girl is: Isabell Hill (22)
 

8. Java Stream max operation example

Similar to the min() operation, the max()is a special reduction operation that returns the maximum element in the stream according to the specified comparator. The following example finds the oldest male person in the list:

Optional<Person> max = listPersons.stream()
			.filter(p -> p.getGender().equals(Gender.MALE))
			.max((p1, p2) -> p1.getAge() - p2.getAge());
if (max.isPresent()) {
	Person oldestMan = max.get();
	System.out.println("The oldest man is: "
				+ oldestMan + " (" + oldestMan.getAge() + ")");
}
Result:

The oldest man is: David Green (39)
 

9. Java Stream reduce operation example

The Stream API provides three versions of reduce() methods which are general reduction operations. Let’s look at each version.

  • Version #1: Optional<T> reduce(BinaryOperator<T> accumulator)
This method performs a reduction on the elements of the stream, using an associative accumulation function, and returns an Optional object describing the reduced value. For example, the following code accumulates first names of all persons into a String:

Optional<String> reducedValue = listPersons.stream()
					.map(p -> p.getFirstName())
					.reduce((name1, name2) -> name1 + ", " + name2);

if (reducedValue.isPresent()) {
	String names = reducedValue.get();
	System.out.println(names);
}
Output:

Alice, Bob, Carol, David, Eric, Frank, Gibb, Henry, Isabell, Jane
 

  • Version #2: T reduce(T identity, BinaryOperator<T> accumulator)
This method is similar to the version #1, but it returns the reduced value of the specified type T. The identity value must be an identity value for the accumulator function, which means it does not affect the result of accumulation. The following example calculates sum of numbers in a stream:

int[] numbers = {123, 456, 789, 246, 135, 802, 791};

int sum = Arrays.stream(numbers).reduce(0, (x, y) -> (x + y));

System.out.println("sum = " + sum);
Output:

sum = 3342
 

  • Version #3:

U reduce(U identity,

             BiFunction<U,? super T,U> accumulator,

             BinaryOperator<U> combiner)

This is the most general reduction method that performs a reduction on elements of the stream, using the provided identity, accumulator and combiner.

The identity element is both an initial seed value for the reduction and a default result if there are no input elements.

The accumulator function takes a partial result and the next element, and produces a new partial result

The combiner function combines two partial results to produce a new partial result (it is necessary in parallel reductions).

The following example shows how this general reduction operation is used to accumulate numbers to calculate sum of them:

int[] numbers = {123, 456, 789, 246, 135, 802, 791};

int sum = Arrays.stream(numbers).reduce(0, (x, y) -> (x + y), Integer::sum);

System.out.println("sum = " + sum);
That’s all about common terminal operations provided by the Stream API. For in-depth information about stream operations, see its Javadoc or read this book.

 

References:

 

Related Java Stream Tutorials

 

Other Java Collections Tutorials:


About the Author:

is certified Java programmer (SCJP and SCWCD). He began programming with Java back in the days of Java 1.4 and has been passionate about it ever since. You can connect with him on Facebook and watch his Java videos on YouTube.



Attachments:
Download this file (JavaStreamTerminalOperationsExamples.zip)JavaStreamTerminalOperationsExamples.zip[Java 8 Stream Terminal Operations Examples]2 kB

Add comment

   


Comments 

#6test2024-04-03 15:24
nice job, some do not compile, but it is ok
Quote
#5Agarty2024-02-28 23:59
Hi! The third example contains an error:

The right decision is:

int sum = Arrays.stream(numbers).reduce(0, Integer::sum);
Quote
#4PAOK2021-08-24 21:29
Bolches yarboclos

Reduce #3 does not compile
Quote
#3PAOK2021-08-23 19:47
Bolches yarboclos

I'd think that sum() is also a terminal operator.
Quote
#2Akash Joshi2019-10-09 03:44
The example for #3 version of reduce() is wrong. As Arrays.stream() would return IntStream and there's no
U reduce(U identity, BiFunction accumulator, BinaryOperator combiner)
version.
Quote