Optional详解
- empty : 创建一个值为null的Optional对象。一般很少用。
 - of : 创建一个非空值的Optional对象。值一定非空,否则将抛出NullPointerException异常。
 - ofNullable : 创建一个可能为空值的Optional对象。
 
Optionalempty = Optional.empty(); // Optional.empty Optional name = Optional.of("孙悟空"); // Optional[孙悟空] 
String[] arr = {null, "非空"};
int index = new Random().nextInt(2);
Optional result = Optional.ofNullable(arr[index]);
String maybe = person.map(p -> "原来真的" + p).orElse("空的");  // 如果person不为空,返回"原来真的非空",否则返回"空的" 
二、判断Optional中的值是否为空
Optional类提供了一个isPresent()方法来判断值是否非空,如果非空返回true,否则返回false。
String[] arr = {null, "非空"};
int index = new Random().nextInt(2);
Optional person = Optional.ofNullable(arr[index]);
if (person.isPresent()) {
  System.out.println(person.get());  // 如果值非空就返回被包装的非空值
} else {
  System.out.println(Optional.empty());  // 如果值为null,则返回EMPTY
} 
isPresent还有一个重载方法isPresent(Consumer<? super T> consumer),其中Consumer是一个函数式接口,可以通过函数式接口给方法传递行为,这是Java 8 最牛的两个特性之一(另一个是Stream)。
该方法的作用是Optional中的值非空,就执行isPresent方法,否则就不执行。如果执行了isPresent方法,至于在isPresent方法中要干什么事,则是借助Consumer函数式接口来传递。
String[] arr = {null, "非空"};
int index = new Random().nextInt(2);
Optional.ofNullable(arr[index])
  .ifPresent(x -> System.out.println("原来真的" + x));  // 如果arr[index]非空,就输出"原来真的非空"
三、读取Optional中的值
Optional类提供了一个get方法用来读取被包装的值,当值非空时,获取该值,否则抛出NoSuchElementException异常。这个方法必须要结合isPresent()一起用,先判断再取值。但是如果是这样,那我们压根就不需要使用Optional对值进行包装,直接用if对值进行判空,更简洁明了。所以这个方法用的不多。
String[] arr = {null, "非空"};
int index = new Random().nextInt(2);
Optional optional = Optional.ofNullable(arr[index]);
if (optional.isPresent()) {
  String s = optional.get();
} 
四、操作Optional中的值
Optional中提供了map和flatMap方法对Optional中的value进行操作,然后返回包装新值的Optional对象。
- map : 如果Optional中的value非空,对value操作之后返回新值的Optional对象。如果value为空,则返回Optional的空对象。
 
String[] arr = {null, "非空"};
int index = new Random().nextInt(2);
Optional optional = Optional.ofNullable(arr[index]);
Optional s = optional.map(e -> "原来真的" + e);  
- flatMap : 如果Optional中的value非空,对value操作之后返回新值的Optional对象,但是新值的Optional对象需要开发者手动封装。如果value为空,则返回Optional的空对象。
 
String[] arr = {null, "非空"};
int index = new Random().nextInt(2);
Optional optional = Optional.ofNullable(arr[index]);
Optional s = optional.flatMap(e -> Optional.of("原来真的" + e));  
为什么会有这种区别,查看源码可以看到,map函数的返回值是Optional.ofNullable(mapper.apply(value)),已经被Optional封装了。而flatMap函数的返回值是Objects.requireNonNull(mapper.apply(value)),它没有被Optional封装,然而flatMap要求返回值是Optional,所以只能手动封装。
public Optional map(Function<? super T, ? extends U> mapper) { Objects.requireNonNull(mapper); if (!isPresent()) return empty(); else { return Optional.ofNullable(mapper.apply(value)); } } public Optional flatMap(Function<? super T, Optional> mapper) { Objects.requireNonNull(mapper); if (!isPresent()) return empty(); else { return Objects.requireNonNull(mapper.apply(value)); } }
flatMap这种设计在多个Optional的链式调用时会用到。
五、Optional中的值为null怎么办
Optional提供了三个方法:orElse、orElseGet 和 orElseThrow,这三个方法都是如果有非空值,就获取值,否则做对应的处理,具体如下:
- orElse:当Optional中的值为空时,给Optional设置一个默认值。
 
String[] arr = {null, "非空"};
int index = new Random().nextInt(2);
Optional optional = Optional.ofNullable(arr[index]);
String s = optional.orElse("");  // 要么是 "非空",要么是 "" 
注意到如果optional非空时,并没有通过get取获取其中的值,orElse方法也可以获取。可以查看如下源码可知,如果value非空,返回value,否则返回other。
public T orElse(T other) { return value != null ? value : other; }
- orElseGet:当Optional中的值为空时,执行Supplier行为,通过这个行为给value设置默认值。这个方法存在是因为,有时候默认值无法简单给出,而是需要通过一系列的逻辑之后才能获得,这时候orElse方法就无法满足,只能使用这个方法。
 
String[] arr = {null, "非空"};
int index = new Random().nextInt(2);
Optional optional = Optional.ofNullable(arr[index]);
String s = optional.orElseGet(() -> {
  System.out.println("一系列逻辑"); 
  return "一系列逻辑之后获取的新值"; 
}); 
- orElseThrow:当Optional中的值为空时,抛出一个异常。
 
String[] arr = {null, "非空"};
int index = new Random().nextInt(2);
Optional optional = Optional.ofNullable(arr[index]);
String s = optional.orElseThrow(() -> new RuntimeException("没有值啊")); 
六、过滤Optional对象
通常我们说过滤都是针对一个列表,然而这里却是针对一个Optional对象,满足条件原样返回,不满足条件返回EMPTY
Optional中提供一个 filter 方法来决定是否返回这个Optional对象,该方法接收函数式接口断言Predicate为入参,如果断言为真且value非空,则返回value非空的Optional对象,否则返回EMPTY;
Integer[] arr = {null, 10,  100};
int index = new Random().nextInt(3);
Optional optional = Optional.ofNullable(arr[index]);
Optional integer = optional.filter(t -> t > 50);  // 当arr[index]为null和10时,都是返回EMPTY  
以上是Optional类的全部功能。