【发布时间】:2017-10-28 10:16:31
【问题描述】:
最近,在使用 Java 8 流时,我在使用以下测试用例时遇到了一个关于 reduce 操作的 NullPointerException:
private static final BinaryOperator<Integer> sum = (a, b) -> {
if (a == null) return b;
if (b == null) return a;
return Integer.sum(a, b);
};
List<Integer> s = new ArrayList<>();
s.add(null);
s.add(null);
s.add(null);
Integer i = s.stream().reduce(sum).orElse(null);
// throws NPE
Integer i = s.stream().reduce(sum).orElse(2);
// throws NPE
Integer i = s.stream().reduce(null,(a, b)->null);
// returns a value i.e null
或者:
Integer i = s.stream().filter(Objects::nonNull).reduce(Integer::sum).orElse(null);
// returns a value i.e null
在检查reduce操作时,我遇到了这个执行reduce操作的类:
class ReducingSink implements AccumulatingSink<T, Optional<T>, ReducingSink> {
private boolean empty;
private T state;
public void begin(long size) {
empty = true;
state = null;
}
@Override
public void accept(T t) {
if (empty) {
empty = false;
state = t;
} else {
state = operator.apply(state, t);
}
}
@Override
public Optional<T> get() {
return empty ? Optional.empty() : Optional.of(state);
}
@Override
public void combine(ReducingSink other) {
if (!other.empty)
accept(other.state);
}
}
在上面的代码中,您看到get() 方法在布尔值empty 为false 时返回一个可选值,在我的情况下该值为false 但state 为null,所以Optional.of(null) 抛出一个NullPointerException。就我而言,我有一个允许null 的二元运算符。
所以我认为代码
return empty ? Optional.empty() : Optional.of(state);
应该改为
return empty || state == null ? Optional.empty() : Optional.of(state);
作为我的二元运算符(它的任务是减少)并且可以使用null。
【问题讨论】:
-
Optional.ofNullable怎么样?无论如何,您的示例看起来不正确,因为您将List<Integer>与BinaryOperator<Double>一起使用。 -
@Pshemo
ReducingSink是一个内部 jdk 类 -
无论如何-@Pshemo 是对的-该示例编译得不是很好:-)
-
你浪费了这么多时间研究源代码,而不是一秒钟查看文档,来了解这种行为是故意的......
-
我知道这种行为是故意的,只是想了解他们的意图
标签: java java-8 java-stream