0

I wonder if there is some alternative way for filtering and unwrapping Optional when using streams in Java 8 than I normally use.

Here is a snippet of some code that uses Optional as part of file error handling when producing some markdown, which might fail on an IO exception, which I'm handling with a failed list.

files.stream()
  .map(f -> {
      try {
          return Optional.of(generateMarkdown(f));
      } catch (IOException e) {
          failed.add(f);
      }
      return Optional.<Markdown>empty();
  })
  .filter(o -> o.isPresent())
  .map(o -> o.get())
  .forEach(h -> { ...

Is there a better way to write the .filter and .map lines, or to rewrite the .map block not to need them?

damon140
  • 11
  • 1
  • 5
  • 3
    You can return null instead and `filter(Objects::nonNull)`. – shmosel Sep 29 '19 at 23:30
  • 1
    Or you can `flatMap(f -> { try { return Stream.of(generateMarkdown(f)) } catch (IOException e) { failed.add(f); } return Stream.empty(); })`. – shmosel Sep 29 '19 at 23:32
  • In addition to answers relating directly to Java 8 Streams, I'll mention that [Vavr types](https://www.vavr.io/) have sensible conversion operations as part of the standard library. – chrylis -cautiouslyoptimistic- Sep 29 '19 at 23:32
  • Take a look at the answers to ["Using Java 8's Optional with Stream::flatMap"](https://stackoverflow.com/questions/22725537/using-java-8s-optional-with-streamflatmap). In short, there's a solution in Java 9, but you have to hack your way around it in Java 8. If you do this more than once or twice, I recommend implementing Java 9's `Optional.stream` as a static method on a utility class. – jirassimok Sep 30 '19 at 00:38
  • While not an answer to your question, you can use method references instead of lambdas: `.filter(Optional::isPresent).map(Optional::get)`. Personally, I find method references cleaner and easier to read. – Slaw Sep 30 '19 at 01:03

1 Answers1

0

Using the answer provided by shmosel is concise. However there are many interesting answers for Java 8 and 9+ discussed in "Using Java 8's Optional with Stream::flatMap".

The rewritten code looks like this:

files.stream()
  .map(f -> {
      try {
          return generateMarkdown(f);
      } catch (IOException e) {
          failed.add(f);
      }
      return null;
  })
  .filter(Objects::nonNull)
  .forEach(h -> { ...
damon140
  • 11
  • 1
  • 5