Java 16

Stream.mapMulti has been added to JDK 16. This enables the following, without intermediate creation of single-element Streams:

Optional<Other> result =
    things.stream()
          .map(this::resolve)
          .<Other>mapMulti(Optional::ifPresent)
          .findFirst();

Java 9

Optional.stream has been added to JDK 9. This enables you to do the following, without the need of any helper method:

Optional<Other> result =
    things.stream()
          .map(this::resolve)
          .flatMap(Optional::stream)
          .findFirst();

Java 8

Yes, this was a small hole in the API, in that it's somewhat inconvenient to turn an Optional<T> into a zero-or-one length Stream<T>. You could do this:

Optional<Other> result =
    things.stream()
          .map(this::resolve)
          .flatMap(o -> o.isPresent() ? Stream.of(o.get()) : Stream.empty())
          .findFirst();

Having the ternary operator inside the flatMap is a bit cumbersome, though, so it might be better to write a little helper function to do this:

/**
 * Turns an Optional<T> into a Stream<T> of length zero or one depending upon
 * whether a value is present.
 */
static <T> Stream<T> streamopt(Optional<T> opt) {
    if (opt.isPresent())
        return Stream.of(opt.get());
    else
        return Stream.empty();
}

Optional<Other> result =
    things.stream()
          .flatMap(t -> streamopt(resolve(t)))
          .findFirst();

Here, I've inlined the call to resolve() instead of having a separate map() operation, but this is a matter of taste.

Answer from Stuart Marks on Stack Overflow
🌐
GeeksforGeeks
geeksforgeeks.org › java › optional-stream-method-in-java-with-examples
Optional stream() method in Java with examples - GeeksforGeeks
July 12, 2025 - The stream() method of java.util.Optional class in Java is used to get the sequential stream of the only value present in this Optional instance. If there is no value present in this Optional instance, then this method returns returns an empty ...
Top answer
1 of 13
371

Java 16

Stream.mapMulti has been added to JDK 16. This enables the following, without intermediate creation of single-element Streams:

Optional<Other> result =
    things.stream()
          .map(this::resolve)
          .<Other>mapMulti(Optional::ifPresent)
          .findFirst();

Java 9

Optional.stream has been added to JDK 9. This enables you to do the following, without the need of any helper method:

Optional<Other> result =
    things.stream()
          .map(this::resolve)
          .flatMap(Optional::stream)
          .findFirst();

Java 8

Yes, this was a small hole in the API, in that it's somewhat inconvenient to turn an Optional<T> into a zero-or-one length Stream<T>. You could do this:

Optional<Other> result =
    things.stream()
          .map(this::resolve)
          .flatMap(o -> o.isPresent() ? Stream.of(o.get()) : Stream.empty())
          .findFirst();

Having the ternary operator inside the flatMap is a bit cumbersome, though, so it might be better to write a little helper function to do this:

/**
 * Turns an Optional<T> into a Stream<T> of length zero or one depending upon
 * whether a value is present.
 */
static <T> Stream<T> streamopt(Optional<T> opt) {
    if (opt.isPresent())
        return Stream.of(opt.get());
    else
        return Stream.empty();
}

Optional<Other> result =
    things.stream()
          .flatMap(t -> streamopt(resolve(t)))
          .findFirst();

Here, I've inlined the call to resolve() instead of having a separate map() operation, but this is a matter of taste.

2 of 13
71

I'm adding this second answer based on a proposed edit by user srborlongan to my other answer. I think the technique proposed was interesting, but it wasn't really suitable as an edit to my answer. Others agreed and the proposed edit was voted down. (I wasn't one of the voters.) The technique has merit, though. It would have been best if srborlongan had posted his/her own answer. This hasn't happened yet, and I didn't want the technique to be lost in the mists of the StackOverflow rejected edit history, so I decided to surface it as a separate answer myself.

Basically the technique is to use some of the Optional methods in a clever way to avoid having to use a ternary operator (? :) or an if/else statement.

My inline example would be rewritten this way:

Optional<Other> result =
    things.stream()
          .map(this::resolve)
          .flatMap(o -> o.map(Stream::of).orElseGet(Stream::empty))
          .findFirst();

An my example that uses a helper method would be rewritten this way:

/**
 * Turns an Optional<T> into a Stream<T> of length zero or one depending upon
 * whether a value is present.
 */
static <T> Stream<T> streamopt(Optional<T> opt) {
    return opt.map(Stream::of)
              .orElseGet(Stream::empty);
}

Optional<Other> result =
    things.stream()
          .flatMap(t -> streamopt(resolve(t)))
          .findFirst();

COMMENTARY

Let's compare the original vs modified versions directly:

// original
.flatMap(o -> o.isPresent() ? Stream.of(o.get()) : Stream.empty())

// modified
.flatMap(o -> o.map(Stream::of).orElseGet(Stream::empty))

The original is a straightforward if workmanlike approach: we get an Optional<Other>; if it has a value, we return a stream containing that value, and if it has no value, we return an empty stream. Pretty simple and easy to explain.

The modification is clever and has the advantage that it avoids conditionals. (I know that some people dislike the ternary operator. If misused it can indeed make code hard to understand.) However, sometimes things can be too clever. The modified code also starts off with an Optional<Other>. Then it calls Optional.map which is defined as follows:

If a value is present, apply the provided mapping function to it, and if the result is non-null, return an Optional describing the result. Otherwise return an empty Optional.

The map(Stream::of) call returns an Optional<Stream<Other>>. If a value was present in the input Optional, the returned Optional contains a Stream that contains the single Other result. But if the value was not present, the result is an empty Optional.

Next, the call to orElseGet(Stream::empty) returns a value of type Stream<Other>. If its input value is present, it gets the value, which is the single-element Stream<Other>. Otherwise (if the input value is absent) it returns an empty Stream<Other>. So the result is correct, the same as the original conditional code.

In the comments discussing on my answer, regarding the rejected edit, I had described this technique as "more concise but also more obscure". I stand by this. It took me a while to figure out what it was doing, and it also took me a while to write up the above description of what it was doing. The key subtlety is the transformation from Optional<Other> to Optional<Stream<Other>>. Once you grok this it makes sense, but it wasn't obvious to me.

I'll acknowledge, though, that things that are initially obscure can become idiomatic over time. It might be that this technique ends up being the best way in practice, at least until Optional.stream gets added (if it ever does).

UPDATE: Optional.stream has been added to JDK 9.

Discussions

Optional.stream()
Functional code doesn’t necessarily mean readable code. With the last changes, I believe it’s both. I believe readability went downhill in this specific example. The amount of wrapping, nesting and type juggling is just too much. The intent is not clear at all at first glance anymore. It seems to be just for the sake of "being functional". What I would do is check for null and have it return an empty list like this: List lines = orderId != null ? orderRepository.findByOrderId(orderId) : Collections.emptyList(); Or just keep the guard and have it return early BigDecimal.ZERO instead of IllegalArgumentException (which would be equivalent to the last example). Additionally it's also a bad example to showcase Optional.stream as you could aswell just start with Stream.ofNullable(orderId) directly (not good either, but better than the roundabout using Optional). More on reddit.com
🌐 r/java
27
8
February 21, 2021
`Optional<Stream>.filter(Optional::isPresent).map(Optional::get)` to Java 11 `.flatMap(Optional::stream)`
What problem are you trying to solve? Java 8 Optional class didn't provide ::stream method. As a result of this unfortunate mistake a popular idiom was created to flatten a Stream of Optionals: .fi... More on github.com
🌐 github.com
2
October 6, 2023
Null safety
I'll post the most workable answer within the confines of java in a separate comment because this will be quite long, but let's first delve into why Optional does not 'work' (will not 'solve' nullity in java) and why you probably shouldn't use it at all: Java introduced the stream API in java ... More on reddit.com
🌐 r/java
229
100
August 13, 2024
Optional list
Side remark: if you know the list will be empty, you don't need to create an empty list that you return; you can return what you get from Collections.emptyList() . E.g. return Collections.emptyList(); More on reddit.com
🌐 r/javahelp
13
3
July 21, 2024
🌐
Oracle
docs.oracle.com › javase › 8 › docs › api › java › util › Optional.html
Optional (Java Platform SE 8 )
April 21, 2026 - Optional<FileInputStream> fis = names.stream().filter(name -> !isProcessedYet(name)) .findFirst() .map(name -> new FileInputStream(name)); Here, findFirst returns an Optional<String>, and then map returns an Optional<FileInputStream> for the desired file if one exists.
🌐
Frankel
blog.frankel.ch › optional-stream
Optional.stream()
February 21, 2021 - public BigDecimal getOrderPrice(Long ... .reduce(BigDecimal.ZERO, BigDecimal::add); } The functional way is to wrap the orderId in an Optional....
🌐
Reddit
reddit.com › r/java › optional.stream()
r/java on Reddit: Optional.stream()
February 21, 2021 - It's wrapping in nullable Optional just to create a one element stream of it. Then goes on with creating a one element Stream containing a list just to break out of it right after.
🌐
Baeldung
baeldung.com › home › java › java streams › filtering a stream of optionals in java
Filtering a Stream of Optionals in Java | Baeldung
January 8, 2024 - One of the options in Java 8 is to filter out the values with Optional::isPresent and then perform mapping with the Optional::get function to extract values: List<String> filteredList = listOfOptionals.stream() .filter(Optional::isPresent) ...
🌐
Medium
medium.com › @Sohjiro › working-with-streams-and-optionals-in-java-8-63dd26401fe6
Working with Streams and Optionals in Java 8 | by Felipe Juárez | Medium
October 2, 2017 - Instead, we can use the Optional class for removing that kind of conditions and just apply functions. Is in this moment were I remember what I told you at the begining: I had thought that the transition from Elixir to Java it would be painful, but Java 8 proved me that is not completely true
Find elsewhere
🌐
GitConnected
levelup.gitconnected.com › java-optional-as-a-stream-c7bd79500619
Java Optional as a Stream. The unique relationship of the Optional… | by Randal Kamradt Sr | Level Up Coding
February 12, 2021 - The Optional type shares several methods with the Stream type, filter, map, and flatMap. In each case, they behave as a Stream does, if the ‘stream’ is empty, each returns empty. In Java 9, using the stream() method of the Optional type brings to bear the entire suite of Stream methods, ...
🌐
GitHub
github.com › openrewrite › rewrite-migrate-java › issues › 313
get)` to Java 11 `.flatMap(Optional::stream)` · Issue #313
October 6, 2023 - Optional<Stream>.filter(Optional::isPresent).map(Optional::get) to Java 11 .flatMap(Optional::stream)#313
Author   openrewrite
🌐
GeeksforGeeks
geeksforgeeks.org › java › stream-in-java
Stream In Java - GeeksforGeeks
Streams help developers write cleaner, shorter, and more readable code for data processing tasks. Allows processing of data without modifying the original collection. Supports parallel processing to improve performance on large datasets. Reduces the need for lengthy loops and temporary variables in code. Java Stream Creation is one of the most basic steps before considering the functionalities of the Java Stream.
Published   3 weeks ago
🌐
Apache Kafka
kafka.apache.org › documentation
Documentation Redirect | Apache Kafka
May 22, 2026 - Redirecting · Security | Donate | Thanks | Events | License | Privacy
🌐
MongoDB
mongodb.com
MongoDB: The World’s Leading Modern Data Platform | MongoDB
Build scalable event-driven applications that react and respond in near real-time. Atlas Stream Processing unifies the developer experience, enabling you to work with high-velocity data streams from sources like Apache Kafka using the same familiar MongoDB Aggregation Pipeline stages you use for your database.
🌐
Zod
zod.dev
Intro | Zod
Introduction to Zod - TypeScript-first schema validation library with static type inference
🌐
Claude API Docs
platform.claude.com › docs › en › build-with-claude › structured-outputs
Structured outputs - Claude API Docs
April 6, 2026 - When using structured outputs, properties in objects maintain their defined ordering from your schema, with one important caveat: required properties appear first, followed by optional properties.
🌐
Coderanch
coderanch.com › t › 728497 › java › Java-Stream-Optional-don-understand
Java 8 Stream, Optional don't understand this particular case (Features new in Java 8 forum at Coderanch)
.map(Optional::stream) returns Stream<Stream<String>>. And whenever you have a Stream.map operation that returns Stream<Stream<T>> for whatever T, using flatMap instead will get rid of the inner Stream part (similar for Optional). Thank You! Rob Spoor · Sheriff · Posts: 22907 · 132 · I ...
🌐
Medium
medium.com › @dinukakasunmedis › exploring-java-optional-with-stream-api-2f091308113a
Exploring Java Optional with Stream API | by Dinuka Kasun Medis | Medium
October 8, 2024 - This is a container object that may or may not contain a value, offering a way to explicitly handle the absence of values rather than encountering null references. When combined with the Java Stream API, Optional becomes a highly useful tool ...
🌐
Java Guides
javaguides.net › 2023 › 09 › java-optional-stream.html
Java Optional stream()
September 28, 2023 - The stream() method of the Optional class in Java is used to transform the Optional instance into a Stream.
🌐
DEV Community
dev.to › nfrankel › optional-stream-38ac
Optional.stream() - DEV Community
February 21, 2021 - public BigDecimal getOrderPrice(Long ... .reduce(BigDecimal.ZERO, BigDecimal::add); } The functional way is to wrap the orderId in an Optional....
🌐
GitHub
gist.github.com › asufana › 341921ab2b31ecf2feb0
Java8 Streamから学ぶOptionalモナドとEitherモナド。
Optional<Integer> n1 = Optional.ofNullable(1); Optional<Integer> n2 = Optional.ofNullable(2); Optional<Integer> n3 = n1.flatMap(i1 -> n2.map(i2 -> i1 + i2)); //n1, n2 のいずれか、あるいは両方が null だろうが意識せずに処理したいことを記述すればよい ⇒複数のOptionalを処理する場合でも、それぞれの値の有無を意識する必要がない ... 要素を取り出して処理する(戻り値なし) list.stream().foreach(f) ⇒ optional.ifPresent(f)