If you change your code to use anyMatch
instead of filter(...).findAny().isPresent()
, it works as expected:
boolean found = Arrays.asList(null, null, 1)
.stream()
.anyMatch(Objects::isNull);
System.out.println(found); // true
As to why your version fails with NPE, in the Stream.findAny
docs it says:
Throws:
NullPointerException - if the element selected is null
So this is expected behavior.
EDIT:
The NPE occurs because Optional.of
is used to construct the value returned by findAny()
. And Optional.of
requires a non-null value, as per the docs:
Returns an Optional with the specified present non-null value.
Anyways, I suppose you'd like to know why Optional.of
was used instead of Optional.ofNullable
, when building the value returned by findAny()
...
Well, I can only speculate, but I think that findAny()
and findFirst()
are meant to find values that match some criteria, i.e. a Person
whose name starts with A
. It can be the case that you want to know whether there's a null
element in your stream. But in this case, you don't need to actually find such element, because you already know that if you find it, it will be, well... just null
. So it's enough to only check if your stream contains null
, and you can perfectly use anyMatch()
to find if that's the case.
In other words, it wouldn't be of much use to find an element that is null
, because you can't do anything with it (apart from knowing that it's null
).
EDIT 2: As user @holi-java indicates in his comment below, if findAny()
returned Optional.ofNullable(null)
, then there would be no way to know whether null
was found or not. In this case, the result would be ambiguous, because Optional.ofNullable(null).equals(Optional.empty()) == true
, i.e. it would result in confusion, since Optional.ofNullable(null).isPresent() == false
, meaning there was no matching value found.