java 8 findFirst vs map on optional

jer*_*zek 5 java nullpointerexception optional java-8 java-stream

鉴于此代码:

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
Run Code Online (Sandbox Code Playgroud)

A线投掷

java.lang.NullPointerException:null

而B行返回null.

这种行为的原因是什么?无论findAny()map()回报Optional<T>.

小智 6

list.stream().map(Foo::getAttr).findAny().orElse(null);
Run Code Online (Sandbox Code Playgroud)

用于流的Java文档说Stream:"返回一个流,该流包含将给定函数应用于此流的元素的结果",而findAny()"可以返回aNullPointerException - 如果选择的元素为null".在类Foo中,默认情况下,Integer(非int)设置为null,因为已声明但未初始化.请参阅基在Java中查看默认值对象初始化

初始化不同于:A)类成员(对象和基元)B)局部变量


hol*_*ava 5

首先,您的两个代码片段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
Run Code Online (Sandbox Code Playgroud)

并且NullPointerException发生在Stream#findAny操作中,因为它无法接受null值。因为它使用Optional.of而不是Optional.ofNullableStream#findAny的文档已经断言:

抛出

NullPointerException- 如果选择的元素为

因此,如果您希望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
Run Code Online (Sandbox Code Playgroud)