nev*_*gqs 77 java optional java-8 java-stream
为什么这会抛出java.lang.NullPointerException
?
List<String> strings = new ArrayList<>();
strings.add(null);
strings.add("test");
String firstString = strings.stream()
.findFirst() // Exception thrown here
.orElse("StringWhenListIsEmpty");
//.orElse(null); // Changing the `orElse()` to avoid ambiguity
Run Code Online (Sandbox Code Playgroud)
第一项strings
是null
,这是一个完全可以接受的值.此外,findFirst()
返回一个Optional,这对于findFirst()
能够处理null
s 更有意义.
编辑:更新orElse()
不那么模棱两可.
das*_*ght 63
这样做的原因是Optional<T>
在回报中使用.不允许包含可选项null
.从本质上讲,它无法区分"它不在那里"和"它在那里,但它被设置为null
"的情况.
这就是为什么文档明确禁止在以下情况null
中选择的情况findFirst()
:
抛出:
NullPointerException
- 如果选择的元素是null
Hol*_*ger 43
正如已经讨论过的API设计师不要认为开发商要治疗null
值和缺失值的方法相同.
如果您仍想这样做,可以通过应用序列明确地执行此操作
.map(Optional::ofNullable).findFirst().flatMap(Function.identity())
Run Code Online (Sandbox Code Playgroud)
到溪边.如果没有第一个元素或者第一个元素是,则在两种情况下结果都是空的可选项null
.所以在你的情况下,你可以使用
String firstString = strings.stream()
.map(Optional::ofNullable).findFirst().flatMap(Function.identity())
.orElse(null);
Run Code Online (Sandbox Code Playgroud)
null
如果第一个元素不存在或得到一个值null
.
如果要区分这些情况,可以省略以下flatMap
步骤:
Optional<String> firstString = strings.stream()
.map(Optional::ofNullable).findFirst().orElse(null);
System.out.println(firstString==null? "no such element":
firstString.orElse("first element is null"));
Run Code Online (Sandbox Code Playgroud)
这与您更新的问题没什么不同.你只需要更换"no such element"
与"StringWhenListIsEmpty"
和"first element is null"
用null
.但如果你不喜欢条件,你也可以实现它:
String firstString = strings.stream().skip(0)
.map(Optional::ofNullable).findFirst()
.orElseGet(()->Optional.of("StringWhenListIsEmpty"))
.orElse(null);
Run Code Online (Sandbox Code Playgroud)
现在,firstString
将是null
一个元素存在但是,null
并且它将"StringWhenListIsEmpty"
在没有元素存在时.
Nat*_*han 12
下面的代码替换findFirst()
用limit(1)
,并替换orElse()
有reduce()
:
String firstString = strings.
stream().
limit(1).
reduce("StringWhenListIsEmpty", (first, second) -> second);
Run Code Online (Sandbox Code Playgroud)
limit()
只允许1个元素到达reduce
.在BinaryOperator
传递到reduce
返回的是1元,否则"StringWhenListIsEmpty"
,如果没有元素到达reduce
.
这个解决方案Optional
的BinaryOperator
优点是没有分配,lambda不会分配任何东西.
您可以java.util.Objects.nonNull
在找到之前使用过滤列表
就像是
list.stream().filter(Objects::nonNull).findFirst();
Run Code Online (Sandbox Code Playgroud)