Java threads: find if a thread contains null

Most likely a duplicate, however I could not find any specific one.

Considering

public static void main(String[] args) { System.out.println( Arrays.asList(null, null, 1) .stream() .filter(obj -> obj == null) .findAny() .isPresent() ); } 

Expectation

It should at least work (return false, because findAny returns Optional).

Actual

NullPointerException thrown

Question

Is this a bug or a function?

Thank you for your opinion and explanation.

+5
source share
4 answers

This behavior is highlighted in the Javadoc for findAny () https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#findAny--

Returns: optionally describing some element of this stream or empty Optional if the stream is empty

Throws: NullPointerException - if the selected item is null

Since you are filtering, so the Stream contains only zeros, you get a NullPointerException as expected.

+9
source

If you change your code to use anyMatch instead of filter(...).findAny().isPresent() , it will work as expected:

 boolean found = Arrays.asList(null, null, 1) .stream() .anyMatch(Objects::isNull); System.out.println(found); // true 

Regarding why your version does not work with NPE, Stream.findAny docs says:

Throws:

NullPointerException - if the element selected is null

So this is the expected behavior.


EDIT: NPE arises because Optional.of used to construct the value returned by findAny() . And Optional.of requires a non-empty value according to the docs:

Returns an optional parameter with the specified current value other than zero.

In any case, I suppose you would like to know why Optional.of used instead of Optional.ofNullable when creating the value returned by findAny() ...

Well, I can only guess, but I think that findAny() and findFirst() are for finding values ​​that match some criteria, i.e. a Person whose name begins with A Perhaps you want to know if there is a null element in your stream. But in this case, you don’t really need to find such an element, because you already know that if you find it, it will, well ... just null . Therefore, it is enough to check only if there is null in your thread, and you can perfectly use anyMatch() to find this case.

In other words, it would be impractical to find the null element, because you cannot do anything with it (not knowing that it is null ).


EDIT 2: As user @ holi-java points out in his comment below, if findAny() returned Optional.ofNullable(null) , then there would be no way to find out if null was found or not. In this case, the result would be mixed, because Optional.ofNullable(null).equals(Optional.empty()) == true , that is, it will lead to confusion, since Optional.ofNullable(null).isPresent() == false , which means that the found matching value was not found.

+8
source

This is not an error, it is the result of calling get() on an Optional instance that calls NPE. The exact call that calls it is findAny() , which gives the following stack trace:

 Exception in thread "main" java.lang.NullPointerException at java.util.Objects.requireNonNull(Objects.java:203) at java.util.Optional.<init>(Optional.java:96) at java.util.Optional.of(Optional.java:108) at java.util.stream.FindOps$FindSink$OfRef.get(FindOps.java:193) at java.util.stream.FindOps$FindSink$OfRef.get(FindOps.java:190) at java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:152) at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.util.stream.ReferencePipeline.findAny(ReferencePipeline.java:469) at StreamTest.main(StreamTest.java:17) 

Also, the documentation for findAny() indicates that an NPE can be thrown:

Throws: NullPointerException - if the selected item is null

You can achieve the expected result with anyMatch() :

 Arrays.asList(null, null, 1).stream().anyMatch(obj -> obj == null) 

Why was not ofNullable() used in the findAny() implementation?

API designers did not want to assume that null means that the value is absent (missing value) or present, but equal to null. Alternatively, you can use map(Optional::isNullable) for any stream.

+2
source

Here is the documentation of findAny() , here is what it says:

Throws : NullPointerException -

if the selected item is null

So, you will always get NPE if you try to call findAny() on a null object.

Instead, you can use anyMatch , for example:

 Arrays.asList(null, null, 1).stream().anyMatch(e -> e == null)); 
+2
source

Source: https://habr.com/ru/post/1268450/


All Articles