The forEach is designed to be a terminal operation and yes - you can't do anything after you call it.

The idiomatic way would be to apply a transformation first and then collect() everything to the desired data structure.

The transformation can be performed using map which is designed for non-mutating operations.

If you are performing a non-mutating operation:

 items.stream()
   .filter(s -> s.contains("B"))
   .map(s -> s.withState("ok"))
   .collect(Collectors.toList());

where withState is a method that returns a copy of the original object including the provided change.


If you are performing a side effect:

items.stream()
  .filter(s -> s.contains("B"))
  .collect(Collectors.toList());

items.forEach(s -> s.setState("ok"))
Answer from Grzegorz Piwowarek on Stack Overflow
🌐
HowToDoInJava
howtodoinjava.com › home › java 8 › java collect stream to list (with examples)
Java Collect Stream to List (with Examples)
April 29, 2024 - Here, we can use Stream.filter() method to pass a predicate that will return only those items which match the given pre-condition. In the given example, we are filtering all employees whose salary is less than 400.
🌐
Stackify
stackify.com › streams-guide-java-8
A Guide to Java Streams: In-Depth Tutorial With Examples
September 4, 2024 - The strategy for this operation is provided via the Collector interface implementation. In the example above, we used the toList collector to collect all Stream elements into a List instance.
🌐
Baeldung
baeldung.com › home › java › java collections › the difference between collection.stream().foreach() and collection.foreach()
The Difference Between stream().forEach() and forEach() | Baeldung
September 17, 2025 - Let’s look at an example where we first call forEach() directly on the collection, and second, on a parallel stream: list.forEach(System.out::print); System.out.print(" "); list.parallelStream().forEach(System.out::print);
🌐
Javaprogramto
javaprogramto.com › 2020 › 12 › java-8-stream-foreach-collect.html
Java 8 Stream foreach Collect - Can not be done? JavaProgramTo.com
December 9, 2020 - Take a list with strings and try to do some filtering and then call forEach(). Finally, call collect method to store the final strings into a ArrayList. package com.javaprogramto.java8.foreach; import java.util.ArrayList; import java.util.List; ...
🌐
Oracle
docs.oracle.com › javase › 8 › docs › api › java › util › stream › Stream.html
Stream (Java Platform SE 8 )
2 weeks ago - Therefore, even when executed in parallel with non-thread-safe data structures (such as ArrayList), no additional synchronization is needed for a parallel reduction. ... Map<String, List<Person>> peopleByCity = personStream.collect(Collectors.groupingBy(Person::getCity));
🌐
Stack Abuse
stackabuse.com › guide-to-java-streams-foreach-with-examples
Guide to Java Streams: forEach() with Examples
July 27, 2020 - AtomicInteger result2 = new AtomicInteger(); targetList.stream().forEach(integer -> { if (integer > 0) result2.addAndGet(1); }); System.out.println("Result: " + result2); The forEach() method is a really useful method to use to iterate over collections in Java in a functional approach.
🌐
GeeksforGeeks
geeksforgeeks.org › java › stream-foreach-method-java-examples
Stream forEach() method in Java with examples - GeeksforGeeks
January 23, 2026 - Example: Java · import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); // Print each number in the list using forEach numbers.strea...
Find elsewhere
🌐
Tabnine
tabnine.com › home page › code › java › java.util.stream.stream
java.util.stream.Stream.forEach java code examples | Tabnine
private List<Symbol> getPushedDownGroupingSet(AggregationNode aggregation, Set<Symbol> availableSymbols, Set<Symbol> requiredJoinSymbols) { List<Symbol> groupingSet = aggregation.getGroupingKeys(); // keep symbols that are directly from the join's child (availableSymbols) List<Symbol> pushedDownGroupingSet = groupingSet.stream() .filter(availableSymbols::contains) .collect(Collectors.toList()); // add missing required join symbols to grouping set Set<Symbol> existingSymbols = new HashSet<>(pushedDownGroupingSet); requiredJoinSymbols.stream() .filter(existingSymbols::add) .forEach(pushedDownGroupingSet::add); return pushedDownGroupingSet; } origin: spring-projects/spring-framework ·
Top answer
1 of 3
12

Instead of using a forEach just use streams from the beginning:

List<PersonWrapper> wrapperList = jrList.stream()
    .flatMap(jr -> seniorList.stream()
         .filter(sr -> jr.getName().equals(sr.getName()))
         .map(sr -> new PersonWrapper(jr, sr))
    )
    .collect(Collectors.toList());

By using flatMap you can flatten a stream of streams (Stream<Stream<PersonWrapper>>) into a single stream (Stream<PersonWrapper>)

If you can't instantiate wrapperList by yourself or really need to append to it. You can alter above snippet to following:

List<PersonWrapper> wrapperList = new ArrayList<>();

jrList.stream()
    .flatMap(jr -> seniorList.stream()
         .filter(sr -> jr.getName().equals(sr.getName()))
         .map(sr -> new PersonWrapper(jr, sr))
    )
    .forEach(wrapperList::add);
2 of 3
4

While Lino's answer is certainly correct. I would argue that if a given person object in jrList can only ever have one corresponding match in seniorList maximum, in other words, if it's a 1-1 relationship then you can improve upon the solution given by Lino by finding the first match as follows:

List<PersonWrapper> resultSet = jrList.stream()
                .map(p -> seniorList.stream()
                        .filter(sr -> p.getName().equals(sr.getName()))
                        .findFirst()
                        .map(q -> new PersonWrapper(p, q))
                        .get())
                .collect(Collectors.toList());

or if there is no guarantee that each person in jrList will have a corresponding match in seniorList then change the above query to:

List<PersonWrapper> resultSet = jrList.stream()
                .map(p -> seniorList.stream()
                        .filter(sr -> p.getName().equals(sr.getName()))
                        .findFirst()
                        .map(q -> new PersonWrapper(p, q))
                        .orElse(null))
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

The difference is that now instead of calling get() on the result of findFirst() we provide a default with orElse in case findFirst cannot find the corresponding value and then we filter the null values out in the subsequent intermediate operation as they are not needed.

🌐
JRebel
jrebel.com › blog › java-streams-in-java-8
Using Java Streams in Java 8 and Beyond | JRebel by Perforce
Collect: This is the way to get out of the streams world and obtain a concrete collection of values, like a list in the example above.Back to top · There are some caveats of using the Java streaming API though, and sometimes stream processing can get out of hand.
🌐
HowToDoInJava
howtodoinjava.com › home › java 8 › java stream foreach()
Java Stream forEach() with Examples - HowToDoInJava
March 14, 2022 - If the provided Consumer action ... synchronization. In this Java example, we are iterating over a Stream of Integers and printing all the integers to the standard output....
🌐
GeeksforGeeks
geeksforgeeks.org › java › difference-between-collection-stream-foreach-and-collection-foreach-in-java
Difference Between Collection.stream().forEach() and Collection.forEach() in Java - GeeksforGeeks
February 2, 2021 - // Java Program to show the ... GFG { public static void main(String[] args) { List<Integer> list = new ArrayList<>(); list.add(5); list.add(6); list.add(3); list.add(4); // printing each element of list using forEach loop ...
🌐
Medium
rameshfadatare.medium.com › java-stream-foreach-examples-8696ed4af274
Java Stream forEach() Examples - Ramesh Fadatare
September 27, 2024 - In this example, we use forEach() to update user records in a database. Assume we have a list of users, and we need to mark each of them as active: import java.util.stream.Stream; public class UpdateUserRecordsExample { static class User { String ...
🌐
Medium
medium.com › @AlexanderObregon › javas-stream-collect-method-explained-956667984a8f
Java’s Stream.collect() Method Explained | Medium
November 28, 2024 - The partitioningBy collector takes a predicate and divides the elements of the stream into two groups: one group where the predicate evaluates to true and another where it evaluates to false. The result is a Map<Boolean, List<T>> structure. When working with numerical data, you can use summarizingInt, summarizingDouble, or summarizingLong to obtain statistical summaries. import java.util.IntSummaryStatistics; import java.util.stream.Collectors; import java.util.stream.Stream; public class SummarizingExample { public static void main(String[] args) { IntSummaryStatistics stats = Stream.of(5, 10, 15, 20) .collect(Collectors.summarizingInt(Integer::intValue)); System.out.println("Count: " + stats.getCount()); // Output: Count: 4 System.out.println("Sum: " + stats.getSum()); // Output: Sum: 50 System.out.println("Average: " + stats.getAverage()); // Output: Average: 12.5 } }
🌐
Java67
java67.com › 2016 › 01 › how-to-use-foreach-method-in-java-8-examples.html
10 Examples of forEach() method in Java 8 | Java67
You can read the code like cake, it's much easier than using Iterator or any other way to loop over List in Java. Now, let's filter out only which has a length greater than 2, for this purpose we can use the length() function of String class: alphabets.stream() .filter(s -> s.length() > 2) .forEach(System.out::println); Apart from forEach, this is also a good example of using the filter method in Java 8 for filtering or selecting a subset of elements from Stream. You can read more about that in the Collections to Streams in Java 8 Using the Lambda Expressions course on Pluralsight, which provides an in-depth explanation of new Java 8 features.
🌐
Medium
medium.com › @code.wizzard01 › java-streams-and-collectors-a-practical-guide-and-cheat-sheet-with-real-world-examples-67dcf84156b5
Java Streams and Collectors: A Practical Guide and Cheat Sheet with Real-World Examples | by Code Wiz | Medium
May 10, 2025 - Terminal Operations: Trigger the processing of the stream and produce a result (e.g., collect, forEach, reduce). These operations are eager and consume the stream. Once a terminal operation is called, the stream cannot be reused. Collectors: Special classes that define how to collect the results of a stream into a specific data structure (e.g., List, Set, Map).
🌐
Medium
medium.com › @AlexanderObregon › javas-collectors-tolist-method-explained-0e90e5d90dcb
Java’s Collectors.toList() Method Explained | Medium
August 23, 2024 - Here is a basic example to illustrate ... main(String[] args) { List<String> collectedList = Stream.of("Red", "Green", "Blue") .collect(Collectors.toList()); collectedList.forEach(System.out::println); } } In this example, a stream ...
🌐
Baeldung
baeldung.com › home › java › core java › guide to the java foreach loop
Guide to the Java forEach Loop | Baeldung
June 17, 2025 - For instance, let’s consider an enhanced for-loop version of iterating and printing a Collection of Strings: List names = List.of("Larry", "Steve", "James", "Conan", "Ellen"); for (String name : names) { LOG.info(name); }
🌐
Java Guides
javaguides.net › 2020 › 04 › java-8-stream-filter-and-foreach-example.html
Java 8 Stream - filter() and forEach() Example
September 14, 2020 - import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; /** * Stream filter and forEach() method example * * @author Ramesh Fadatare * */ public class StreamFilterExample { public static void main(String[] args) { // using stream API List < Product > filteredProducts = getProducts().stream() .filter((product) -> product.getPrice() > 25000 f) .collect(Collectors.toList()); filteredProducts.forEach(System.out::println); } private static List < Product > getProducts() { List < Product > productsList = new ArrayList < Product > (); productsList.add(new Product(1, "HP Laptop", 25000 f)); productsList.add(new Product(2, "Dell Laptop", 30000 f)); productsList.add(new Product(3, "Lenevo Laptop", 28000 f)); productsList.add(new Product(4, "Sony Laptop", 28000 f)); productsList.add(new Product(5, "Apple Laptop", 90000 f)); return productsList; } }