Given this code:
class Foo {
Integer attr;
public Integer getAttr() {return attr;}
}
List<Foo> list = new ArrayList<>();
list.add(new Foo());
list.stream().map(Foo::getAttr).findAny().orElse(null); //A
list.stream().findAny().map(Foo::getAttr).orElse(null); //B
Line A throws
java.lang.NullPointerException: null
while line B returns null.
What is the cause of this behaviour? Both findAny()
and map()
return Optional<T>
.
When Stream is unordered, findFirst() and findAny() are the same. But when Stream is ordered, findAny() will be better.
The findAny() method returns any element from a Stream, while the findFirst() method returns the first element in a Stream.
In a nutshell, the Optional class includes methods to explicitly deal with the cases where a value is present or absent. However, the advantage compared to null references is that the Optional class forces you to think about the case when the value is not present.
The stream() method of java. util. Optional class in Java is used to get the sequential stream of the only value present in this Optional instance. If there is no value present in this Optional instance, then this method returns returns an empty Stream.
list.stream().map(Foo::getAttr).findAny().orElse(null);
Java doc for streams says that Stream: "returns a stream consisting of the results of applying the given function to the elements of this stream", and findAny() "could return aNullPointerException - if the element selected is null". In your class Foo, Integer(not int) by default is set to null because is declared but not initialized. see Primitives see default values and Object initialization in Java
Initialization is different for: A) Class Members (Objects and primitives) B) Local Variables
First, your two code snippet map
are different operations:
// v--- stream intermediate operation
list.stream().map(Foo::getAttr).findAny().orElse(null); //A
// v---- a Optional utility method
list.stream().findAny().map(Foo::getAttr).orElse(null); //B
and the NullPointerException
occurs in Stream#findAny operation, since it can't accept a null
value. due to it uses Optional.of rather than Optional.ofNullable. and the documentation of Stream#findAny is already asserts:
Throws:
NullPointerException
- if the element selected is null
so if you want your A
code snippet works fine you must filter all null
values before calling Stream#findAny, for example:
//when no elements in stream, `findAny` will be return a empty by Optional.empty()
// v
list.stream().map(Foo::getAttr).filter(Objects::nonNull).findAny().orElse(null);//A
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