3

I'm searching for an elegant way to stream only non-empty Optional entries using the StreamEx library. Or the standard library, if it's possible.

Currently I'm using the following, rather verbose, approach:

List<Optional<String>> list = 
   Arrays.asList(Optional.of("A"), Optional.empty(), Optional.of("B"));

List<String> nonEmpty = 
   StreamEx.of(list).filter(Optional::isPresent).map(Optional::get).toList();

I'm essentially looking for something like StreamEx's nonNull method, but for Optional.

Henrik Aasted Sørensen
  • 6,966
  • 11
  • 51
  • 60
  • 2
    Java 9: `List nonEmpty = list.stream().flatMap(Optional::stream).toList();` – Holger Jan 24 '18 at 09:58
  • 4
    you should add that as an answer actually, not a comment/edit. I would upvote... and SO encourages this also. good find! – Eugene Jan 24 '18 at 10:26
  • I believe you have a wrong design, if you have that situation. You should not add elements which do not have their values. So I consider it as a wrong design, try to avoid using optional in that way. Instead, give responsibility to your sources, where your data comes from, they should give you values, not empty placeholders. – nick318 Jan 24 '18 at 10:26
  • 4
    @NikitaSalomatin I suppose, the list is just an example. The real life case might be more of `streamOfOrdinaryValues .map(functionThatReturnsOptional) /*the issue of the question*/ .toList();`… – Holger Jan 24 '18 at 10:38
  • @NikitaSalomatin: The example is condensed. You have a point, but I'd argue that the situation will often arise in real-world settings. – Henrik Aasted Sørensen Jan 24 '18 at 11:10

2 Answers2

6

Well this has been added, but only in java-9:

list.stream()
    .flatMap(Optional::stream)
    .collect(Collectors.toList());

There is a back-port from Stuart Marks here

Eugene
  • 117,005
  • 15
  • 201
  • 306
  • Yeah, unfortunately I'm on Java 8. Do have StreamEx available, though, and was hoping that it would have a shortcut similar to what you're showing. – Henrik Aasted Sørensen Jan 24 '18 at 10:06
  • @Henrik I'd just live with that, it's not that much of a big deal... until you upgrade to 9 – Eugene Jan 24 '18 at 10:07
  • 5
    But you can do shorter than Stuart Marks: `.flatMap(o -> o.map(Stream::of).orElse(null))` – Holger Jan 24 '18 at 10:08
  • 3
    @Holger beautiful! I could not understand it right away, but then *if a mapped Stream is null an empty stream is used, instead* – Eugene Jan 24 '18 at 10:23
2

A bit of research into the StreamEx issue backlog revealed issue 49, which provides a shorter approach and contains a discussion on the topic:

List<String> nonEmpty = StreamEx.of(list).flatMap(StreamEx::of).toList();

Shorter, although whether it's more readable is up for discussion.

Henrik Aasted Sørensen
  • 6,966
  • 11
  • 51
  • 60