What you are looking for is called the map operation:

Thing[] functionedThings = Arrays.stream(things).map(thing -> functionWithReturn(thing)).toArray(Thing[]::new);

This method is used to map an object to another object; quoting the Javadoc, which says it better:

Returns a stream consisting of the results of applying the given function to the elements of this stream.

Note that the Stream is converted back to an array using the toArray(generator) method; the generator used is a function (it is actually a method reference here) returning a new Thing array.

Answer from Tunaki on Stack Overflow
🌐
Stack Abuse
stackabuse.com › guide-to-java-streams-foreach-with-examples
Guide to Java Streams: forEach() with Examples
July 27, 2020 - The forEach() method is a really useful method to use to iterate over collections in Java in a functional approach. In certain cases, they can massively simplify the code and enhance clarity and brevity. In this article, we've gone over the basics of using a forEach() and then covered examples of the method on a List, Map and Set. We've covered the difference between the for-each loop and the forEach(), as well as the difference between basing logic on return values versus side-effects.
Discussions

Return from lambda forEach() in java - Stack Overflow
Code against interfaces, so code against List over ArrayList. Use diamond inference for the type parameter in new ArrayList<>(), you are using Java 8 after all. ... You again want to convert something of legacy Java to Java 8 without looking at the bigger picture. This part has already been answered by @IanRoberts, though I think that you need to do players.stream().filter(...)... over what he suggested. ... If you want to return ... More on stackoverflow.com
🌐 stackoverflow.com
Return List from forEach using Stream in java - Stack Overflow
I am trying to convert below for-loop to forEach method with help Stream function using Java1.8, but I was messed up and also confused to do that. List valueList = new ArrayList ()... More on stackoverflow.com
🌐 stackoverflow.com
How to get a list output from forEach loop in Java 8 Streams - Stack Overflow
I have two different lists of same objects but different properties and with a common identifier in those objects. I would like to iterate over the first list and get the corresponding object from ... More on stackoverflow.com
🌐 stackoverflow.com
.forEach() on a list vs .forEach() on a stream. What's the difference?
Please ensure that: Your code is properly formatted as code block - see the sidebar (About on mobile) for instructions You include any and all error messages in full - best also formatted as code block You ask clear questions You demonstrate effort in solving your question/problem - plain posting your assignments is forbidden (and such posts will be removed) as is asking for or giving solutions. If any of the above points is not met, your post can and will be removed without further warning. Code is to be formatted as code block (old reddit/markdown editor: empty line before the code, each code line indented by 4 spaces, new reddit: https://i.imgur.com/EJ7tqek.png ) or linked via an external code hoster, like pastebin.com, github gist, github, bitbucket, gitlab, etc. Please, do not use triple backticks (```) as they will only render properly on new reddit, not on old reddit. Code blocks look like this: public class HelloWorld { public static void main(String[] args) { System.out.println("Hello World!"); } } You do not need to repost unless your post has been removed by a moderator. Just use the edit function of reddit to make sure your post complies with the above. If your post has remained in violation of these rules for a prolonged period of time (at least an hour), a moderator may remove it at their discretion. In this case, they will comment with an explanation on why it has been removed, and you will be required to resubmit the entire post following the proper procedures. To potential helpers Please, do not help if any of the above points are not met, rather report the post. We are trying to improve the quality of posts here. In helping people who can't be bothered to comply with the above points, you are doing the community a disservice. I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns. More on reddit.com
🌐 r/learnjava
9
5
September 29, 2023
🌐
TutorialsPoint
tutorialspoint.com › break-or-return-from-java-8-stream-foreach
Break or return from Java 8 stream forEach?
Read More: Java Stream API Improvements. The forEach method is a terminal operation, which runs action on each element of the stream. It?s meant to process each element; it doesn?t allow early exit by break or return. List names = Arrays.asList("Alice", "Bob", "Charlie"); names.stream().forEach(name -> { System.out.println(name); });
🌐
GeeksforGeeks
geeksforgeeks.org › java › stream-foreach-method-java-examples
Stream forEach() method in Java with examples - GeeksforGeeks
January 23, 2026 - import java.util.*; class GFG { public static void main(String[] args) { List<Integer> list = Arrays.asList(2, 4, 6, 8, 10); // Sort in reverse order and print each element list.stream() .sorted(Comparator.reverseOrder()) .forEach(System.out::println); } } ... import java.util.*; class GFG { public static void main(String[] args) { List<String> list = Arrays.asList("GFG", "Geeks", "for", "GeeksforGeeks"); // Print each string in the stream list.stream().forEach(System.out::println); } }
🌐
Tabnine
tabnine.com › home page › code › java › java.util.stream.stream
java.util.stream.Stream.forEach java code examples | Tabnine
* @param packages one or more base package classes */ public Builder basePackage(String... packages) { Arrays.stream(packages).filter(StringUtils::hasText).forEach(this::addBasePackage); return this; } ... @Override public Collection<CommandFactory<?>> lookup() { List<CommandFactory<?>> list = new ArrayList<>(); commands.stream().forEach(list::add); return list; }
🌐
Medium
rameshfadatare.medium.com › java-stream-foreach-examples-8696ed4af274
Java Stream forEach() Examples - Ramesh Fadatare
September 27, 2024 - Here’s another real-world use case where we send an email to each user in a list using the forEach() method: import java.util.stream.Stream; public class SendEmailsExample { static class User { String email; User(String email) { this.email = email; } @Override public String toString() { return email; } } public static void main(String[] args) { Stream<User> users = Stream.of( new User("alice@example.com"), new User("bob@example.com"), new User("charlie@example.com") ); // Use forEach() to send an email to each user users.forEach(user -> System.out.println("Sending email to: " + user)); } } Output: Sending email to: alice@example.com Sending email to: bob@example.com Sending email to: charlie@example.com ·
🌐
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 - Java only requires all threads to finish before any terminal operation, such as Collectors.toList(), is called. 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);
🌐
W3Docs
w3docs.com › java
Break or return from Java 8 stream forEach?
However, since forEach() is a terminal operation and is not intended to be used as a loop, it is generally better to use a different method such as findFirst() or anyMatch() if you only need to find a single element in the stream. Here's an example of how you can use findFirst() to find the first even number in a stream and return from the operation: List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); Integer result = numbers.stream() .filter(n -> n % 2 == 0) .findFirst() .orElse(null); System.out.println(result); // prints 2
Find elsewhere
Top answer
1 of 6
164

The return there is returning from the lambda expression rather than from the containing method. Instead of forEach you need to filter the stream:

players.stream().filter(player -> player.getName().contains(name))
       .findFirst().orElse(null);

Here filter restricts the stream to those items that match the predicate, and findFirst then returns an Optional with the first matching entry.

This looks less efficient than the for-loop approach, but in fact findFirst() can short-circuit - it doesn't generate the entire filtered stream and then extract one element from it, rather it filters only as many elements as it needs to in order to find the first matching one. You could also use findAny() instead of findFirst() if you don't necessarily care about getting the first matching player from the (ordered) stream but simply any matching item. This allows for better efficiency when there's parallelism involved.

2 of 6
20

I suggest you to first try to understand Java 8 in the whole picture, most importantly in your case it will be streams, lambdas and method references.

You should never convert existing code to Java 8 code on a line-by-line basis, you should extract features and convert those.

What I identified in your first case is the following:

  • You want to add elements of an input structure to an output list if they match some predicate.

Let's see how we do that, we can do it with the following:

List<Player> playersOfTeam = players.stream()
    .filter(player -> player.getTeam().equals(teamName))
    .collect(Collectors.toList());

What you do here is:

  1. Turn your input structure into a stream (I am assuming here that it is of type Collection<Player>, now you have a Stream<Player>.
  2. Filter out all unwanted elements with a Predicate<Player>, mapping every player to the boolean true if it is wished to be kept.
  3. Collect the resulting elements in a list, via a Collector, here we can use one of the standard library collectors, which is Collectors.toList().

This also incorporates two other points:

  1. Code against interfaces, so code against List<E> over ArrayList<E>.
  2. Use diamond inference for the type parameter in new ArrayList<>(), you are using Java 8 after all.

Now onto your second point:

You again want to convert something of legacy Java to Java 8 without looking at the bigger picture. This part has already been answered by @IanRoberts, though I think that you need to do players.stream().filter(...)... over what he suggested.

🌐
Java67
java67.com › 2016 › 01 › how-to-use-foreach-method-in-java-8-examples.html
10 Examples of forEach() method in Java 8 | Java67
Once the list is filtered then forEach() method will print all elements starting with String "a", as shown below: alphabets.stream() .filter(s -> s.startsWith("a")) .forEach(System.out::println); This is cool, right?
🌐
Mkyong
mkyong.com › home › java8 › java 8 foreach examples
Java 8 forEach examples - Mkyong.com
December 4, 2020 - We can now reuse the same Consumer method and pass it to the forEach method of List and Stream. ... package com.mkyong.java8.misc; import java.util.*; import java.util.function.Consumer; import java.util.stream.Stream; public class ForEachConsumer { public static void main(String[] args) { List<String> list = Arrays.asList("abc", "java", "python"); Stream<String> stream = Stream.of("abc", "java", "python"); // convert a String to a Hex Consumer<String> printTextInHexConsumer = (String x) -> { StringBuilder sb = new StringBuilder(); for (char c : x.toCharArray()) { String hex = Integer.toHexString(c); sb.append(hex); } System.out.print(String.format("%n%-10s:%s", x, sb.toString())); }; // pass a Consumer list.forEach(printTextInHexConsumer); stream.forEach(printTextInHexConsumer); } }
🌐
Javaprogramto
javaprogramto.com › 2020 › 05 › java-break-return-stream-foreach.html
How to Break or return from Java Stream forEach in Java 8 JavaProgramTo.com
May 13, 2020 - The CustomForEach logic can be used for return statement also. One the condition is met then stop or skip the next all values in the stream. This will reduce the overhead in processing very large streams. package com.javaprogramto.java8.str...
🌐
Baeldung
baeldung.com › home › java › core java › guide to the java foreach loop
Guide to the Java forEach Loop | Baeldung
June 17, 2025 - The article is an example-heavy introduction of the possibilities and operations offered by the Java 8 Stream API. ... In Java, the Collection interface has Iterable as its super interface. This interface has a new API starting with Java 8: ... Simply put, the Javadoc of forEach states that it “performs the given action for each element of the Iterable until all elements have been processed or the action throws an exception.”
🌐
HowToDoInJava
howtodoinjava.com › home › java 8 › java stream foreach()
Java Stream forEach() with Examples - HowToDoInJava
March 14, 2022 - The forEach() method is a terminal operation. It means that it does not return an output of type Stream.
🌐
Codemia
codemia.io › knowledge-hub › path › break_or_return_from_java_8_stream_foreach
Break or return from Java 8 stream forEach?
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises
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.

Top answer
1 of 3
3

Alternative 2 looks best to me in this case

1. Readability

  • Alternative 2 has less number of lines
  • Alternative 2 read more close to return a list containing number divisible by 6 from numList, while forEach approach means add number divisible by 6 from numList to secondInts
  • filter(i -> i % 6 == 0) is straight forward and
    if(i % 6 != 0) {
        return;
    }
    
    require some time for human brain to process.

2. Performance

From Stream.toList()

Implementation Note: Most instances of Stream will override this method and provide an implementation that is highly optimized compared to the implementation in this interface.

We benefit from optimization from JDK by using Stream API.

And in this case, using forEach and adding element one by one will be slower, especially when the list is large. It is because ArrayList will need to extend it capacity whenever the list full, while Stream implementation ImmutableCollections.listFromTrustedArrayNullsAllowed just store the result array into ListN.

One more point to note about parallelism:
From Stream#forEach

The behavior of this operation is explicitly nondeterministic. For parallel stream pipelines, this operation does not guarantee to respect the encounter order of the stream, as doing so would sacrifice the benefit of parallelism. For any given element, the action may be performed at whatever time and in whatever thread the library chooses. If the action accesses shared state, it is responsible for providing the required synchronization.

numbersList.stream().parallel()
       .forEach(i -> {
           if(i % 6 != 0) {
               return;
           }
           secondInts.add(i);
       });

Will provide unexpected result, while

List<Integer> third = numbersList.stream().parallel()
      .filter(i -> i % 6 == 0).sorted().forEach()
      .toList();

is totally fine.

3. Flexibility

Imagine you want the filtered list to be sorted, in forEach approach, you can do it like:

numbersList.stream().sorted().
       .forEach(i -> {
           if(i % 6 != 0) {
               return;
           }
           secondInts.add(i);
       });

Which is much slower compared to

numbersList.stream()
        .filter(i -> i % 6 == 0)
        .sorted()
        .toList();

As we need to sort the whole numbersList instead of filtered.

Or if you want to limit your result to 10 elements, it is not straight forward to do so with forEach, but just as simple as adding limit(10) when using stream.

4. Less error prone

Stream API usually return Immutable object by default.

From Stream.toList()

Implementation Requirements: The implementation in this interface returns a List produced as if by the following: Collections.unmodifiableList(new ArrayList<>(Arrays.asList(this.toArray())))

Meaning that the returned list is immutable by default. Some advantages of immutability are:

  1. You can safely pass the list around to different method without worrying the list is modified.
  2. Immutable list are thread safe.

Read Pros. / Cons. of Immutability vs. Mutability for further discussion.

2 of 3
1

I don’t think it’s an issue of advantages. Each mechanism has a specific purpose.

.forEach() returns void so it doesn’t have an output. The intent is that the elements that the forEach iterates through are not modified. The data in the elements are used for some sort of calculation. I find that forEach is used much less than map. It’s a terminal point in a pipeline.

.filter() takes a stream as input and emits a filtered stream as output. It is for filtering.

.map() is like forEach but it emits a stream of modified objects. It allows the same modification to be done on each each element so that it can be saved, filtered or manipulated further.

.toList is a handy shortcut to turn a stream into a list. Using forEach(List::add) where a toList() will do the work is a terrible idea. You’re preventing Java from bulking the activity.