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 string B returns null.

What is the reason for this behavior? Both findAny()and map()return Optional<T>.

+4
source share
4 answers
list.stream().map(Foo::getAttr).findAny().orElse(null);

Java doc , Stream: " , " findAny() " aNullPointerException - null". Foo Integer ( int) null, , . . Java

: A) ( ) B)

+5

, - , , , findAny : throws NullPointerException if the element selected is null

map(Foo::getAttr), null, null; , findAny ( findAny )

Foo, Foo::getAttr ( , Optional.empty()), orElse.

, ( ):

 list.stream()
     .findAny()
     .flatMap(f -> Optional.ofNullable(f.getAttr()))
     .orElse(null);

flatMap Optional<Integer> (), empty orElse.

+3

-, map - :

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

NullPointerException Stream # findAny, null. - Optional.of, .NNullable. Stream # findAny :

NullPointerException - null

, , A , null , Stream # findAny, :

//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
+2
list.stream().map(Foo::getAttr)

... null.

JavaDoc findAny() ( findFirst()) :

:

a , , empty ,

:

NullPointerException - null

, findAny() , : , , NullPointerException.

, Optional ( JavaDoc, ):

,

... , , Optional.ifPresent( x -> x.method()) NullPointerException - , x .

findAny() Optional.of(null). Optional.empty() , , , .

Many parts of the infrastructure Stream/ are Optionalaimed at preventing the use of zeros.

You can get around this by matching nulls with Optionalsto get Optional<Optional<Foo>>- which looks a bit confusing but is an accurate representation of your domain. Optional.empty()means the stream is empty. Optional.of(Optional.empty())means he found one empty element:

list.stream().map(Foo::getAttr).map(Optional::ofNullable).findAny()
0
source

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


All Articles