我开始学习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()
将返回true
,get()
将返回该值。
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。