java8 -函数式编程之Optional

前言

    在某些状况下,首先要判断某个参数或者某个方法的返回值是否为null,才能继续操做该参数。对于某些链式操做须要屡次经过if语句判断是否为空,才能确保不抛出NullPointerException,这段非空判断的代码显得很是冗长和恶心。好比下面这段代码:java

String isoCode = "default";
if (user != null) {
    Address address = user.getAddress();
    if (address != null) {
        Country country = address.getCountry();
        if (country != null) {
            isocode = country.getIosCode();
            if (isocode != null) {
                isocode = isocode.toUpperCase();
            }
        }
    }
}

    在java 8里,JDK引入了一个Optional类,该类是一个能够为null的容器对象。若是值存在则isPresent()方法会返回true,调用get()方法会返回该对象。经过本文的学习,咱们看下如何经过Optional类重写上面那段判空代码。ios

    接下来,咱们一块儿学习Optional类的初始化和它里面的方法。lambda表达式和四个基本函数式接口是本文的基础,能够经过 java8 -函数式编程之Lambda表达式 和 java8 -函数式编程之四个基本接口 充分了解。编程

Optional初始化

    Optional类的构造方法是私有方法,因此只能经过它的静态工厂方法进行初始化。它的初始化方法有以下四种:app

(1) <T> Optional<T> of (T value) :为非null的值建立一个Optional。若是传入参数为null,抛出NullPointerException。函数式编程

//调用工厂方法建立Optional实例
Optional<String> name = Optional.of("hello");
//传入参数为null,抛出NullPointerException.
Optional<String> someNull = Optional.of(null);

(2)<T> Optional<T> ofNullable (T value) :为指定的值建立一个Optional,若是指定的值为null,则返回一个空的Optional。它和 of 的区别是能够传null值。在它的实现代码中,若是传的值为null,会调用另外一个静态工厂方法 empty 获取一个Optional对象函数

Optional empty = Optional.ofNullable(null);

(3)<T> Optional<T> empty () :ofNullable静态工厂方法,传null值时的实现,返回一个空的Optional。学习

Optional类的其它方法

(1)isPresent :若是值存在返回true,不然返回false。测试

// false
Optional<String> empty = Optional.ofNullable(null);
System.out.println(empty.isPresent());

// true
Optional<String> optionalS2 = Optional.of(s2);
System.out.println(optionalS2.isPresent());

(2)get:若是Optional有值则将其返回,不然抛出NoSuchElementExceptionspa

//获取hello
Optional.of("hello").get();
//抛出NoSuchElementException
Optional.empty().get();

(3)void ifPresent (Consumer<? super T> consumer) :若是Optional实例有值则调用consumer,不然不作处理。.net

//调用ifPresent方法里面的consumer
Optional.of("hello")
        .ifPresent(System.out::println);

(4)orElse:若是有值则将其返回,不然返回指定的其它值

//输出:null
System.out.println(Optional.empty().orElse("null"));
//输出:hello
System.out.println(Optional.of("hello").orElse("null"));

(5)T orElseGet (Supplier<? extends T> other) :orElseGet与orElse方法相似,区别在于获得的默认值。orElse方法将传入的字符串做为默认值,orElseGet方法能够接受 Supplier接口 的实现用来生成默认值。

//输出null
System.out.println(Optional.empty().orElseGet(() -> "null"));
//输出hello
System.out.println(Optional.of("hello").orElseGet(() -> "null"));

(6)<X extends Throwable> T orElseThrow (Supplier<? extends X> exceptionSupplier) throws X :若是有值则将其返回,不然抛出supplier接口建立的异常。

//抛出exception
try {
    Optional.empty().orElseThrow(()->new Exception("为空"));
} catch (Exception e) {
    e.printStackTrace();
}

(7)<U> Optional<U> map (Function<? super T, ? extends U> mapper) :若是参数 mapper 有值,则调用map方法执行mapper参数的Function方法获得返回值。若是mapper的返回值不为null,则建立包含mapping返回值的Optional做为map方法返回值,不然返回空Optional。若是传入的mapper参数是null,抛出NullPointerException。

//输出 JACK
Optional<String> stringOptional = Optional.of("jack").map((value) -> value.toUpperCase());
System.out.println(stringOptional.orElse("default"));

//输出 default
Optional<String> stringOptional1 = Optional.of("jack").map((value) -> null);
System.out.println(stringOptional1.orElse("default"));

//输出 default,而且不会调用mapper
String s2 = null;
Optional<String> stringOptional2 = Optional.ofNullable(s2).map((value) -> value.toUpperCase());
System.out.println(stringOptional2.orElse("default"));

//若是参数mapper为null,抛NullPointerException异常
try {
    String s3 = null;
    Optional<String> stringOptional3 = Optional.ofNullable(s3).map(null);
    System.out.println(stringOptional3.orElse("default"));
} catch (Exception e) {
}

(8)<U> Optional<U> flatMap (Function<? super T, Optional<U>> mapper) :flatMap与map方法相似,区别在于flatMap中的mapper返回值必须是Optional。调用结束时,flatMap不会对结果用Optional封装。

//flatMap,输出 JACK
Optional<String> stringOptional4 = Optional.of("jack").flatMap((value) -> Optional.ofNullable(value.toUpperCase()));
System.out.println(stringOptional4.orElse("default"));

//flatMap,输出 default
Optional<String> stringOptional5 = Optional.of("jack").flatMap((value) -> Optional.ofNullable(null));
System.out.println(stringOptional5.orElse("default"));

//flatMap,输出 default,而且不会调用mapper
String s6 = null;
Optional<String> stringOptional6 = Optional.ofNullable(s6).flatMap((value) -> Optional.ofNullable(value.toUpperCase()));
System.out.println(stringOptional6.orElse("default"));

//flatMap 若是map的参数mapper为null,抛NullPointerException异常
try {
    String s7 = null;
    Optional<String> stringOptional7 = Optional.ofNullable(s7).flatMap(null);
    System.out.println(stringOptional7.orElse("default"));
} catch (Exception e) {
    System.out.println("出错了");
}

(9)Optional<T> filter (Predicate<? super T> predicate) :若是有值而且知足断言条件返回包含该值的Optional,不然返回空Optional。

//输出default
String filterString = Optional.of("hugo")
        .filter(s -> "jack".equals(s))
        .orElse("default");
System.out.println(filterString);
//输出hugo
String filterString2 = Optional.of("hugo")
        .filter(s -> "hugo".equals(s))
        .orElse("default");
System.out.println(filterString2);
//输出default,断言接口里面的语句不会执行
String nullableString = null;
String filterString3 = Optional.ofNullable(nullableString)
        .filter(s -> {
            System.out.println("测试是否调用");
            return "jack".equals(s);
        })
        .orElse("default");
System.out.println(filterString3);

 

解决问题

通过上面学习Optional的相关API,已经对它有了必定的了解。下面,咱们运用上面的知识解决在前言中遗留的问题。

ioscode = Optional.ofNullable(user)
        .map(u -> u.getAddress())
        .map(addr -> addr.getCountry())
        .map(country -> country.getIosCode())
        .map(String::toUpperCase)
        .orElse("default");

从上面的学习能够知道,只有Optional是empty的,map方法不会被调用。

相关资料

Java 8 函数式编程系列

    java8 -函数式编程之Lambda表达式

    java8 -函数式编程之四个基本接口

    java8 -函数式编程之Optional

    java8 -函数式编程之Stream

相关文章
相关标签/搜索