Java 8 Optional——避免空指针异常的小工具

函数式接口(行为参数化)、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
  • max
  • min
  • 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

posted @ 2021-04-22 17:08  小小怪医芙兰  阅读(444)  评论(0编辑  收藏  举报