First, check if the Optional is present. If yes, then stream the list and filter the non-empty ones and print each of them.

optionalList.ifPresent(list -> list.stream()
            .filter(Optional::isPresent)
            .map(Optional::get)
            .forEach(System.out::println));

Almost similar for the stream case too

optionalStream.ifPresent(stream -> stream
            .filter(Optional::isPresent)
            .map(Optional::get)
            .forEach(System.out::println));
Answer from Thiyagu on Stack Overflow
🌐
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 - This approach is similar to the ... Optional value is or isn’t present: List<String> filteredList = listOfOptionals.stream() .flatMap(Optional::stream) .collect(Collectors.toList());...
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
java - How to convert an Optional<T> into a Stream<T>? - Stack Overflow
I upvoted this because Java 9 has some non-backward compatible changes for some projects in their current state. Some projects, such as lombok, are part of core corporate artifacts that are slow to be changed. 2017-10-05T20:05:47.183Z+00:00 ... If by any chance your optional happens to contain a List instead of a single String object, you just need to replace Stream... More on stackoverflow.com
🌐 stackoverflow.com
Why does Optional.of(List<String).stream() return a stream with a single element, the List<String> instead of a Stream of individual elements?
I have an API that returns Response , and I'd like to validate the Response, then get the List and turn that into a Stream.of(Thing), but I have to do an awkward .map(St... More on github.com
🌐 github.com
2
November 19, 2018
lambda - Iterate over an optional list of integers ifPresent - Stack Overflow
I have an Optional list of integers. I wish to see if the list is actually present and then convert it into a stream. One way of doing this is Optional listOfNumbers = ... More on stackoverflow.com
🌐 stackoverflow.com
July 24, 2018
🌐
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....
🌐
Javabeginnerstutorial
javabeginnerstutorial.com › code-base › how-to-use-optional-in-java-8-streams
How to use optional in java 8 streams - Java Beginners Tutorial
August 14, 2023 - Like in this case NO_NAME will be provided when name is null. name = list.stream() .map(jbt::getName) .map(name1 -> name1.orElse("NO_NAME")) .collect(Collectors.<em>joining</em>(",")); System.<em>out</em>.println(name); } } class jbt { private String name; private Integer age; public jbt(String name, Integer age) { this.name = name; this.age = age; } public Optional<String> getName() { if (name == null) { return Optional.<em>empty</em>(); } return Optional.<em>of</em>(name); } public Optional<Integer> getAge() { if (age == null) { return Optional.<em>empty</em>(); } return Optional.<em>of</em>(age); } }
🌐
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
🌐
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 list › convert an optional to an arraylist in java
Convert an Optional to an ArrayList in Java | Baeldung
March 7, 2025 - One of the advantages of using Java Stream API is that it allows us to process elements conditionally and perform various transformations. Imagine we only want to add values to the ArrayList if they meet certain criteria. Streams allow us to incorporate filter() before collecting elements into a list: Optional<String> optionalValue = Optional.of("Hello, World!"); List<String> arrayList = optionalValue .filter(e -> e.startsWith("H")) .stream() .collect(Collectors.toList()); assertTrue(arrayList.contains("Hello, World!"));
Find elsewhere
🌐
GitHub
github.com › aNNiMON › Lightweight-Stream-API › issues › 173
Why does Optional.of(List<String).stream() return a stream with a single element, the List<String> instead of a Stream of individual elements? · Issue #173 · aNNiMON/Lightweight-Stream-API
November 19, 2018 - I have an API that returns Response<List<Thing>>, and I'd like to validate the Response, then get the List and turn that into a Stream.of(Thing), but I have to do an awkward .map(Stream::of).orElse(Stream.empty()) instead of the more intuitive .stream() because .stream() just gives me a stream of the List<Thing> instead of multiple Things. Is this by design? final List<String> flintstones = new ArrayList<String>(){{ add("Fred"); add("Wilma"); add("Pebbles"); add("Dino"); }}; Optional.ofNullable(flintstones) // .stream() // gives me a stream with a single value: List<String> .map(Stream::of).orElse(Stream.empty()) // gives me what I want, four Strings .forEach(System.out::println);
Author   aNNiMON
🌐
GeeksforGeeks
geeksforgeeks.org › java › optional-stream-method-in-java-with-examples
Optional stream() method in Java with examples - GeeksforGeeks
July 12, 2025 - Optional: Optional[9455] Getting the Stream: 9455 Program 2: ... // Java program to demonstrate // Optional.stream() method import java.util.*; public class GFG { public static void main(String[] args) { // create a Optional Optional<Integer> op = Optional.empty(); // print value System.out.println("Optional: " + op); try { // get the Stream System.out.println("Getting the Stream:"); op.stream().forEach(System.out::println); } catch (Exception e) { System.out.println(e); } } } Output:
🌐
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)
March 28, 2020 - It will only produce a Stream<Optional<Car>> if the return type of getCar() is Optional<Car>.If the name optCar means that Stream is indeed handling Optionals<Car>, then you want to look in the Optional documentation, where you find what the flatMap() method does.
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.

🌐
TutorialsPoint
tutorialspoint.com › what-is-the-use-of-the-optional-stream-method-in-java-9
What is the use of the Optional.stream() method in Java 9?\\n
June 11, 2025 - When you have a stream of Optional objects, you can use flatMap(Optional::stream) to filter out empty optionals and extract the present values into a new stream.
Top answer
1 of 2
6

You may do it this way:

return visits.stream()
             .map(visit -> visit.orElse(null))
             .filter(Objects::nonNull)
             .collect(Collectors.toList());

Assuming visits is of type List<Optional<Visit>>.

Causes Of Your Code Not Compiling

Assuming that the variable visits is of type List<Optional<Visit>> the statement you posted:

Stream.of(visits).filter(value -> Optional.isPresent(value))
                 .map((Visit t) -> Optional.get(t))
                 .collect(Collectors.toList());

has the following problems:

  1. Stream.of() takes either one element or many elements of type T and creates a Stream. You use visits as one element of type List<Optional<Visit>> and I think you intend to get a Stream of Optional<Visit> which you may achieve by using visits.stream().

  2. filter(value -> Optional.isPresent(value)) does invoke isPresent(T t) in a static way while the method isPresent(T t) doesn't exist, neither statically nor as an instance method. I think what you intend to do is: filter(value -> value.isPresent()) which is equal to filter(Optional::isPresent). The difference of the second is that Optional::isPresent does not invoke a static method but results in a method reference.

  3. map((Visit) t -> Optional.get(t)) does as well invoke a method get(T t) in a static way which doesn't exist, neither statically nor as an instance method. I think you intended to invoke map((Visit) t -> t.get()) which is equal to map(Optional::get).

Fixing those issues would result in the new statement:

visits.stream().filter(Optional::isPresent)
               .map(Optional::get)
               .collect(Collectors.toList());

The difference to my solution is only that you map after filter. As a reader to get it right you need to remember that Optional::get will always return a non-null value. If you map first and filter second you do not have to remember there are no null values because you filter them out in the second step.

2 of 2
4

You could do it as follows:

List<Visit> visitsWithoutOptionals = visits.stream()
    .filter(Optional::isPresent)
    .map(Optional::get)
    .collect(Collectors.toList());
🌐
GitHub
gist.github.com › Allan-Gong › 548fea5f9eb2e71c0470cee4be593a6e
Options to flatMap a list of Optionals in Java8 · GitHub
Options to flatMap a list of Optionals in Java8. GitHub Gist: instantly share code, notes, and snippets.
🌐
Foojay
foojay.io › home › optional.stream()
Learning About Optional.stream() in OpenJDK and Java | foojay
August 23, 2021 - public BigDecimal getOrderPrice(Long ... .reduce(BigDecimal.ZERO, BigDecimal::add); } The functional way is to wrap the orderId in an Optional....
🌐
Medium
medium.com › @viraj_63415 › when-to-use-optional-stream-4ba745565f43
When to use Optional.stream(). Learn to integrate Java Optional into a… | by Viraj Shetty | Medium
February 6, 2024 - When to use Optional.stream() Learn to integrate Java Optional into a stream Pipeline Java Optional Optional class was introduced in JDK 8, as a means to reduce the occurrence of NullPointerException …
🌐
Baeldung
baeldung.com › home › java › core java › guide to java optional
Guide To Java Optional | Baeldung
February 15, 2026 - Java has a very fluent and elegant Stream API that can operate on the collections and utilizes many functional programming concepts. The newest Java version introduces the stream() method on the Optional class that allows us to treat the Optional instance as a Stream.
🌐
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 - Streams can process data collections, and Optional is often used to handle results safely. Here are common scenarios where Optional and Stream API work hand-in-hand: These terminal operations return an Optional, meaning the result may or may not be present. List<String> names = Arrays.asList("Alice", "Bob", "Charlie"); Optional<String> firstName = names.stream() .filter(name -> name.startsWith("B")) .findFirst(); firstName.ifPresent(System.out::println); // Output: Bob