mapToLong不起作用后过滤非空

时间:2018-12-12 15:07:40

标签: java lambda filter

我的代码是这样

class A {
    private Long b;

    public Long getB() {
        return b;
    }

    public void setB(Long b) {
        this.b = b;
    }

    public static void main(String[] args) {
        A a1 = new A();
        List<A> list = new ArrayList<>();
        list.add(a1);
        list.stream().mapToLong(A::getB).filter(Objects::nonNull).sum();
    }
}

我想过滤null,但是它不起作用,并给我NullPointerException。
如果我在mapToLong之前进行过滤,例如

list.stream().filter(a -> a.getB()!=null).mapToLong(A::getB).sum();

效果很好。我想知道为什么。

4 个答案:

答案 0 :(得分:4)

mapToLongLong转换为long-如果是null,则确实会出现异常。

您需要过滤null转换前的

list.stream()
    .map(A::getB)
    .filter(Objects::nonNull)   //filter the nulls first
    .mapToLong(Long::longValue) //then convert to primitive
    .sum();

答案 1 :(得分:2)

您将m = df['A'].notna() c = m.cumsum() def f(x): lens = len(x.index) a = np.arange(lens) return a // (lens / 2) == 0 mask = c[~m].groupby(c).transform(f) #should be removed #mask = mask.reindex(df.index, fill_value=False) df['B'] = df['A'].where(mask, df['A'].bfill()).ffill().bfill() print (df) A B 0 NaN 4.0 1 NaN 4.0 2 4.0 4.0 3 NaN 4.0 4 NaN 7.0 5 7.0 7.0 6 NaN 7.0 7 NaN 7.0 8 NaN 1.0 9 NaN 1.0 10 1.0 1.0 11 NaN 1.0 12 NaN 6.0 13 6.0 6.0 14 NaN 6.0 15 NaN 6.0 传递给ToLongFunction函数,这是它的签名

mapToLong

您传递方法引用long applyAsLong(T value); -在这里,将您的A::getB并通过拆箱将其返回(从b转换为原始{{1 }}。由于为空,因此将导致NPE。

通过尽早进行过滤,可以避免这种情况的发生。

请参阅:https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html

答案 2 :(得分:2)

此处

list.stream().mapToLong(A::getB).filter(Objects::nonNull).sum();

您正尝试将列表中的每个B转换为Long,然后不过滤任何null。现在,由于您尚未过滤空值,因此您尝试转换空值。那会抛出NullPointerException。

这里

list.stream().filter(a -> a.getB()!=null).mapToLong(A::getB).sum();

您没有过滤任何null,然后将其映射并转换为Long。在尝试转换时,这里没有null,因为您已经过滤了它们,因此没有NullPointerException。

答案 3 :(得分:2)

为什么此代码失败?

list.stream().mapToLong(A::getB).filter(Objects::nonNull).sum();

因为流操作是顺序执行的。因此,如果对于流A::getB的任何元素未返回不为空的Long,则在收集期间将引发异常。

为什么成功?

list.stream().filter(a -> a.getB()!=null).mapToLong(A::getB).sum();

因为首先执行的filter()删除了导致a::getB操作的空元素。 因此,您只能在流collection中添加非null元素。所以也不例外。 但是问题是您执行了两次映射a::getB。重复且无助,即使在这里它并不昂贵(仅仅是吸气剂)。
您想要的是:

list.stream()       
    .map(A::getB) // return Stream<Long> that may contain null
    .filter(Objects::nonNull) // filter null elements
    .mapToLong(s->s) // map Long to long
    .sum(); // sum