如果项目符合条件,是否有办法跳出 java 流?

Is there a way to step out of a java stream if an item matches a condition?

我有一个整数列表,我需要求出其中各项的总和。如果列表包含任何 null 项,则结果应为 null。我当前的实现:

intList.stream().anyMatch(Objects::isNull) ? null : intList.stream().mapToInt(Integer::intValue).sum();

这可以用一个连续的流来完成吗?如果项目满足条件,是否有终止流的操作?

您可以控制总和减少的方式:

Integer sum = intList.stream().reduce(0, (i1, i2) -> {
        if(i1 == null) return null;
        if(i2 == null) return null;
        return i1 + i2;
    });

可能正在使用像这样的 reduce:

List<Integer> intList = Arrays.asList(1,2,3,null,4);
Integer sum = intList.stream().reduce(0, (a, b) -> a == null || b == null ? null: a + b);
System.out.println(sum);

流并不总是正确的解决方案。即使它们是,它们也可能不如简单的循环解决方案那么有效。对于您的情况,我会执行以下操作:

public static Integer sum(List<Integer> vals) {
    int sum = 0;
    for (Integer v : vals) {
        if (v == null) {
            return null;
        }
        sum += v;
    }
    return sum;
}

这对元素或短路求和,returns 为空值。

关于您的问题“如果项目满足条件,是否有终止流的操作?”,Java 9 介绍了执行此操作的 Stream::takeWhile

但是,将此用于您的用例会导致 null 之前的所有内容的总和(不是您实际返回 null 所期望的)。对于您的情况,并且仅限于 JDK,使用 proposed by M A 是最好的(尽管它在达到 null 时不会停止)。

实际最好的方法是将 takeWhileInclusive 与 reduce 操作相结合。不幸的是,takeWhileInclusive 不存在于 JDK 中。然而,Tagir Valeev, who is a committer in the JDK, has written a stream extension library (StreamEx) which has StreamEx::takeWhileInclusive。可能会有用。

以下示例使用该库,如果遇到 null 则跳出 null,否则跳出总和:

StreamEx.of(intList).takeWhileInclusive(Objects::nonNull)
    .reduce(0, (a, b) -> a == null || b == null ? null : a + b);