gpt4 book ai didi

java - NPE on java stream reduce操作

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:50:14 24 4
gpt4 key购买 nike

最近,在处理 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);
}
}

在上面的代码中,如果 boolean 值 empty 为 false,您会看到 get() 方法返回一个可选值,在我的例子中该值为 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

最佳答案

我真的不知道为什么你必须处理空值,这似乎是一个糟糕的开始。而且,如您所见,您不能使用 null 作为输入来reduce。您可以构建自己的自定义 Collector(您不能构建自己的 Reducer)。

你有什么:

 Double result = s.stream()
.filter(Objects::nonNull)
.reduce(Double::sum)
.orElse(null);

非常好 顺便说一句。获得空结果的唯一方法是当输入中的所有元素都为空时,因此最初过滤它们是可行的方法。为了好玩,我决定编写一个自定义收集器(说不出为什么,我想这会很有趣)

 Double result = s.stream()
.parallel()
.collect(
() -> new Double[] { null },
(left, right) -> {
if (right != null) {
if (left[0] != null) {
left[0] = right + left[0];
} else {
left[0] = right;
}
}
},
(left, right) -> {
if (right[0] != null) {
if (left[0] != null) {
left[0] = right[0] + left[0];
} else {
left[0] = right[0];
}
}})[0];

如果需要,您可以将其放入类中:

 class NullableCollector implements Collector<Double, Double[], Double> {

@Override
public BiConsumer<Double[], Double> accumulator() {
return (left, right) -> {
if (right != null) {
if (left[0] != null) {
left[0] = right + left[0];
} else {
left[0] = right;
}
}
};
}

@Override
public Set<Characteristics> characteristics() {
return EnumSet.noneOf(Characteristics.class);
}

@Override
public BinaryOperator<Double[]> combiner() {
return (left, right) -> {
if (right[0] != null) {
if (left[0] != null) {
left[0] = right[0] + left[0];
} else {
left[0] = right[0];
}
}
return left;
};
}

@Override
public Function<Double[], Double> finisher() {
return (array) -> array[0];
}

@Override
public Supplier<Double[]> supplier() {
return () -> new Double[] { null };
}

}

关于java - NPE on java stream reduce操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44219879/

24 4 0