函数式接口(行为参数化)、Stream、Optional是独立的三个部分,在Java中,他们却能组成一个漂亮的三重奏。函数式接口本身限制很大,它就像天生为Stream设计的,而Optional也是Stream处理终端操作结果的一个重要方式。
创建Optional
Optional.empty()
,创建空Optional
Optional.of(value)
,包装value到Optional内部,如果强行传null的话,汇报NullPointerException
ofNullable(value)
,同上,但是可以传递null,这样会生成
Optional.empty
Optional本身是一个包装类,如果按照它的API合理操作,可以避免空指针异常问题.
if (optString.isPresent()){
ostString.get();
}else{
//....
除了上面最基本的套路——先验证再取值的方式,还有一些方法可以将两步合一步的方式。
ifPresent(Consumer),如果值存在就调用Consumer消费,否则什么也不做
orElse(otherObj),如果存在就get,否则返回otherObj
orElseGet(Supplier),如果存在就get,否则返回Supplier的生成对象
orElseThrow(Supplier),存在就get,否则返回Supplier生成的异常
其他的都是显而易见的,对于生成异常,这里有个示例,
optString.orElseThrow(()->new Exception("supplier"));
具体代码Optionals.java
返回Optional的流操作
findFirst
findAny
reduce
IntStream等数字Stream,使用的average
filter(Predicate),如果通过测试,则返回;如果没通过,或者Optional本身为空,则返回Optional.empty()
示例代码OptionalFilter.java
map(Function<T,R>),将Optional内部的值通过Function转化,返回包装结果的Optional;如果内部value为空,则返回Optional.empty()
。
示例代码OptionalMap
flatMap(Function<T,R>),与map一样,提取Optional内部的值,进行转化。不同的是,它不会自动将value包装进Optional,这一点需要调用者自己提供能够返回Optional的Function。
示例代码OptionalFlatMap.java
处理Optional流
所谓Optional流,就是元素为Optional类型的Stream,当我们想处理null值的时候,自然会想到Optional
。
将普通的流转化成Optional,
Stream.generate(Signal::morse)
.map(signal->Optional.ofNullable(signal));
这里的Signal::morse是普通Supplier函数。(注意当使用::
的时候,jvm会自动根据函数签名,将其包装成Supplier对象,不需要函数显示的实现Supplier接口)。
消费Optional流,
optSingnalStream.limit(10)
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(System.out::println);
首先通过filter
过滤掉空值,再通过map选出包装value。如果不这么做,直接打印的话,是一个个Optional对象,而不是其内包含的值。
示例代码StreamOfOptionals.java
我变秃了,但是没变强