Streaming Optional

The amazing Optional class in Java can sometimes be a bit frustrating; what if you have a bunch of them and want a nice and tidy Stream to do some work? If the “bunch” is a List or similar, then no problem. But what if not?

Let’s explore this subject. Here is a little test class that gets us a “bunch” of optional strings:

It doesn’t do anything useful, but it does give us a “bunch” of strings 🙂
Notice the neat output from Optional.toString() by the way.

Now, let’s say we want the strings collected with “:” between them, i.e. joined as a new String.

The obvious solution is of course to make a List or similar, and then add the values we get to that.
Let’s change the main method:

Hmm, we sort of lost the Optional bit somewhere. And what if we actually want an empty string to be a valid value? The trusty old null to tell them apart? Bleh, this doesn’t work.

Let’s return to Optional with a List<Optional<String>>:
(yay for nested generics!)

We obviously need an extra .map() step to “unpack” our (non-empty) strings, so I added that too.

OK, this will work. So why bother with anything else? Well, there are a few cases where it is useful to know how 🙂

Let’s say we have some optional strings and a few empty ones, and maybe a null one just for fun. All wrapped in Optionals of course. And we want to join the whole lot together as a string – without the empty values. Wow, very useful indeed! Please imagine a sensible situation here instead of this nonsense.

Anyway, here goes:

Looks good enough to me?! Maybe not so beautiful, but at least it works?

OK, I promised you a stream from a bunch of optionals without a list in between.
Here is a slightly noobish (i.e. Java 7) way to achieve that:

Wow, we saved one whole character by going from .stream() to .build(), impressive! Not to mention two less imports since we got rid of List and ArrayList. Wow.

Well, not so fast 🙂 There is a neater and more “Java 8” way to do this:

Now we are talking! Try doing that with a List! 🙂

Realizing that both .add() and .accept() exist for Stream.Builder, the curious will of course ask why, and the answer is that .accept() is inherited from the Consumer interface. They do the same thing anyway (unless you get really fancy and subclass Stream.Builder but let’s not go there).

It sort of looks nicer to use .accept() when treating it as a consumer so I tend to do that 🙂

The Consumer is a bit neat though, since it lets us do this:

Notice the fancy stuff going on at line 13?
Of course, this is also possible on a List after some mapping (or even using Stream.Builder.add()).

What this final version does and why it works is trivial and is left as an exercise for the reader to figure out. 🙂

As always, should you be caught doing this, I will disavow any knowledge of your actions.

One thought on “Streaming Optional

  1. Reply

    armin walland

    Nice 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *

Please answer this amazingly complicated math question to prove that you are not a spam bot: