0

How can I get the actual stream in order to filter or map methods from an Optional ? For instance

Optional.ofNullable(id)
        .map(this:loadAllById) // method loadAllById return a stream (now is wrapped in Optional<Stream>)
        .filter(obj -> obj.status) // here i have no access to object in stream but to the full stream 

From this a doubt also arises. Is it correct to have a stream inside an Optional? Since the stream should always be not null (in case empty) shouldn't the check be needed?

Dada
  • 6,313
  • 7
  • 24
  • 43
Sabbullo
  • 1
  • 3
  • 1
    Yeah, you're mixing two APIs: Optional and Stream. Try `.map(this:loadAllById).orElseGet(Stream::empty).filter(...)`: `filter` will now be Stream's, not Optional's. – sp00m Jul 07 '22 at 10:09
  • 1
    The general consensus seems to be that container elements like collections or streams are better off represented as empty elements, instead of wrapped in an `Optional`. – MC Emperor Jul 07 '22 at 10:10

1 Answers1

6

Here, you don't need to use Optinal at all.

Optional was not designed to perform null-checks and Optional.ofNullable(id) is an abuse of optional (see Should Optional.ofNullable() be used for null check?). Use an explicit null-check instead.

An empty stream can represent the absence of data, you don't need an empty optional for that. Make your method loadAllById() return a stream Stream<Foo> instead of optional of stream Optional<Stream<Foo>>. Wrapping a stream with an optional isn't a proper usage of optional (as it has been already mentioned in the comments by @MC Emperor).

That's how your code might look like:

public Stream<Foo> getFoosById(Long id, Status status) {
    if (id == null) {
        return Stream.empty();
    }
    
    return loadAllById(id).filter(foo -> foo.getStatus().equals(status));
}

If status is an enum you can check reference equality with ==.

Alexander Ivanchenko
  • 25,667
  • 5
  • 22
  • 46