2

Suppose I have an Optional containing a Stream:

Optional<Stream<Integer>> optionalStream = Optional.of(Stream.of(1, 2, 3));

Now I need to extract the Stream itself. If the Optional is empty, you want to get an empty Stream.

I'm looking of is something like flatStream() that performs transformation in one step. How can I do this?

My current attempt:

Stream<Integer> stream = optionalStream.stream().flatMap(Function.identity());

The Context of the Problem

In my real scenario, I have something like this, which gives me a Stream<Optional<Foo>>:

stream.findFirst().map(e -> e.getChildren())
Alexander Ivanchenko
  • 25,667
  • 5
  • 22
  • 46
Dario Viva
  • 215
  • 1
  • 10

2 Answers2

8

Use Stream.empty()

It doesn't make sense to wrap a Stream with an Optional.

An Optional allows to interact safely with the result of the method call, which might not produce the data. And empty Optional represents the case when the data is absent.

A Stream can also be empty, and it represents the absents of data perfectly fine without a need of being packed into an Optional.

Use Stream.empty() as a return value for your method.

You also might want to check these references:

Addressing the Question-update

Optional.stream()

The best solution to the problem is to eliminate the problem.

The spirit of the answer remains unchanged: don't create an Optional<Stream<T>> and there would be no need to deal with it.

Java 9 Optional.stream() comes to the rescue. Apply stream() after findFirst(), and you would get either a singleton-stream containing a value captured by findFirst(), or an empty stream. And then you can perform any transformation you need.

So, instead of this:

stream.findFirst().map(e -> e.getChildren())

Do the following:

stream.findFirst().stream().flatMap(Foo::getChildren)

Stream.limit()

Alternatively, as suggested by @Holger instead of findFirt() you can apply limit(1) and continue to chain stream-operation. This approach would work with JDK 8.

stream.limit(1).flatMap(Foo::getChildren)
Alexander Ivanchenko
  • 25,667
  • 5
  • 22
  • 46
  • I get an optional by having a stream, getting the first item of the stream (resulting in an optional) and then mapping the optional to its children (resulting in the aforementioned optionalStream) – Dario Viva Nov 12 '22 at 22:22
  • 1
    @DarioViva Sounds like you're using `findFist()` and then generating a `Stream` from the element wrapped with the resulting `Optional`, right? If so I would advise to make use of the Java 9 [`Optional.stream()`](https://docs.oracle.com/en/java/javase/17/docs/api//java.base/java/util/Optional.html#stream()), i.e. apply `findFirst().stream() ... `. The best solution to the problem is to **eliminate the problem**. – Alexander Ivanchenko Nov 12 '22 at 22:34
  • 1
    @DarioViva I've the description of your real case from the comment to the question and addressed it in the answer (see the update). – Alexander Ivanchenko Nov 12 '22 at 23:10
3

I guess you could use the orElseGet() method:

optionalStream.orElseGet(()->Stream.empty())
  • 2
    I didn’t think of that, but thats exacly what I looked for. With method reference it looks even cleaner IMHO. `optionalStream.orElseGet(Stream::empty)` – Dario Viva Nov 12 '22 at 22:24