if all matched is false, I mean if all the function in .map method, it will rise a NullPointException
Since you're getting a NullPointerException
that means that your code compiles and running. Therefore, I assume that the "code" inside the map()
operation isn't your actual code because we can't treat elements in the of Stream<VersionNumber>
as optionals.
flatMap(Optional::stream)
will not cause a compilation error only if preceding map()
produces a result of type Optional<VersionNumber>
.
Hence, my suggestion is simple: never return null
in place of optional. It's completely wrong when an optional object might be null
, it should either contain a value or be empty, but it should never be null
.
And as @Andy Thomas has pointed out in the comment, there's no reason to utilize Optional
if the code inside the map()
really creates the object on the spot like new VersionNumber(tmp[0], tmp[1], tmp[2]));
. In this case, wrapping the result of the map()
with an Optional
will be a misuse of optional. Return either VersionNumber
instance or null
. And then apply a filter:
.map(vs -> {
if (vs.matches("^matched string$")) {
...
return new VersionNumber(tmp[0], tmp[1], tmp[2]);
}
return null;
})
.filter(Objects::nonNull)
.collect(Collectors.toList());
You have to resort to the usage of optional only if inside the map you're actually not creating VersionNumber
as you've shown, but, for instance, making an API call which return an Optional<VersionNumber>
if some condition is meat.
.map(vs -> {
if (vs.matches("^matched string$")) {
...
return getVersionNumber(tmp[0], tmp[1], tmp[2]); // method returing Optional<VersionNumber>
}
return Optional.empty();
})
.flatMap(Optional::stream)
.collect(Collectors.toList());
In such a case, there's no need to apply filtering. Optional.stream()
when invoked on an empty optional produces an empty stream.