Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java 8 findFirst vs map on optional

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>.

like image 974
jerzy.burzek Avatar asked Jul 07 '17 07:07

jerzy.burzek


People also ask

Which is faster findAny or findFirst?

When Stream is unordered, findFirst() and findAny() are the same. But when Stream is ordered, findAny() will be better.

What is the difference between findFirst () and findAny ()?

The findAny() method returns any element from a Stream, while the findFirst() method returns the first element in a Stream.

Why is null better than optional?

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.

How do you handle optional streams?

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.


2 Answers

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

like image 144
LuCG Avatar answered Sep 22 '22 10:09

LuCG


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
like image 32
holi-java Avatar answered Sep 20 '22 10:09

holi-java