Most probably a duplicate, however I was not able to find any particular one.
public static void main(String[] args) {
System.out.println(
Arrays.asList(null, null, 1)
.stream()
.filter(obj -> obj == null)
.findAny()
.isPresent()
);
}
Should at least work (i.e return false because findAny returns Optional).
NullPointerException
is thrown
Is it a bug or a feature?
Thanks for your opinion and explanation.
1.1 Java Stream Filter or using the static nonNull() method provided by the java. util. Objects class. This method returns true if the allocated reference is not null, otherwise false.
We can use lambda expression str -> str!= null inside stream filter() to filter out null values from a stream.
You have to consume the stream to find out if it's empty. That's the point of Stream's semantics (laziness). To check that the stream is not empty you have to attempt to consume at least one element. At that point the stream has lost its "virginity" and cannot be consumed again from the start.
Return Value : Stream empty() returns an empty sequential stream. Note : An empty stream might be useful to avoid null pointer exceptions while callings methods with stream parameters.
This behavior is highlighted in the Javadoc for findAny() https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#findAny--
Returns:an Optional describing some element of this stream, or an empty Optional if the stream is empty
Throws:NullPointerException - if the element selected is null
Since you are filtering so the Stream only contains nulls, you are getting a NullPointerException as expected.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With