System.out.println() 的 Stream#reduce() 意外打印结果周围的"Optional[]"



我开始学习Java 8的Lambda表达式,并编写了下面的程序来获取列表中所有数字的总和:

import java.util.Arrays;
import java.util.List;
public class MainClass {
    public static void main(String[] args) {
        List<Integer> number = Arrays.asList(1, 2, 3, 4, 5);
        System.out.println(number.stream().reduce((c,e) -> {
            return c + e;
        }));
    }
}

我期望输出是:

15

但我得到了:

可选[15]

Java 版本:1.8.0_45

  • 请解释输出中的 Optional[] 是什么意思?
  • 它在Java 8中有什么意义吗?

从 Java Docs for Stream#reduce((,我们看到 reduce 操作返回一个Optional<T>。如果存在值,则 Optional 只是包装一个值,否则为"空"。

Optional的重要操作包括 Optional#isPresent,它让你知道 Optional 中是否有某些内容,Optional#get,它返回包装在 Optional 中的T,如果在 Empty 上调用时引发异常,以及 Optional#orElse,它返回包装在 Optional 中的T(如果存在(,或者返回在 Empty 上调用时提供的默认值。

对于您的情况,reduce()返回Optional<Integer>背后的理由是,您尝试减少的列表可能是空的。在这种情况下,应返回的Integer没有明确定义。对于您的特定意图0是可以接受的(因为空列表中元素的总和0(,因此您可以按如下方式获得总和:

int sum = number.stream().reduce((c,e) -> c + e).orElse(0);

这样,即使列表为空,您仍将获得定义列表总和的结果。

reduce(BinaryOperator<T> accumulator)

返回描述缩减结果的Optional

Optional

可能包含也可能不包含非 null 值的容器对象。如果存在值,isPresent()将返回trueget()将返回该值。

reduce()返回 Optional 的原因是,流可能是空的,在这种情况下,将没有要减少的内容,即没有值,并且将返回一个Optional.empty()

为了避免

在返回中具有 Optional 功能,您可以调用其他方法 https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#reduce-T-java.util.function.BinaryOperator - 只需在添加 lambda 表达式之前添加标识:"0"。请注意,现在只有一个 0 作为 reduce 调用的第一个参数。

 System.out.println(number.stream().reduce(0,(c,e) -> {
            return c + e;
        }));

只返回

15
知道了

,谢谢@Mshnik和@TimoSta。根据 Optional 的源代码<>它覆盖toString方法

@Override
public String toString() {
    return value != null
        ? String.format("Optional[%s]", value)
        : "Optional.empty";
}

上面的代码在我的输出流中添加了该Optional[]

来自 java.lang.Object.Optional:

可能包含也可能不包含非 null 值的容器对象。如果存在一个值,isPresent(( 将返回 true,get(( 将返回该值。

Optional提供了两种不同的主要方法来检索其值。

public T get() 只是返回包含在Optional中的值,但如果Optional不包装值,则会抛出NoSuchElementException

orElse(T other) 返回包含在 Optional 或 other 中的值(如果Optional未将值括起来(。

编辑(感谢@Brian Goetz(:通常,orElse() 是更好的选择,因为如果Optional包含 null 值,get()返回NoSuchElementException。诚然,在这种情况下,您将始终收到一个Optional值,但主要使用 orElse() 仍然是很好的做法。

所以,在你的情况下,你会改变

System.out.println(number.stream().reduce((c,e) -> {
        return c + e;
}));

自:

System.out.println(number.stream().reduce((c,e) -> {
        return c + e;
}).orElse(0));

这将返回所需的值 15

正如@Brian Goetz在评论中所说,如果你真的想让它简洁,你可以使用Integer::sum和方法参考:

System.out.println(number.stream.reduce(Integer::sum).orElse(0))

这相当于使用较长的 lambda。

最新更新