Optional的简单理解
Optional的简单理解
在上篇博客简单讲解了 Stream 的基本用法,Stream的许多终端操作返回类型为 Optional 类型,第一次见到这个类型,看了源码及网上的资料有了简单的理解。
1、Optional 介绍
Optional 是 JDK8 新增的一个类,看了下源码,可以知道 Optional 是一个用来存储对象的辅助类,可以判断对象是否为空并进行后续操作。
2、Optional 创建
除了 Stream 方面的应用,如果平常需要使用 Optional,有以下三种方法创建 Optional。
2.1、Optional.empty()
private static final Optional<?> EMPTY = new Optional<>();
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
直接创建一个空的Optional。
2.2、Optional.of()
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
如果传进来的对象为 null , 则会抛出异常。
2.3 Option.ofNullable()
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
传进来的对象可以为 null。
3、常用方法
3.1、isPresent()
isPresent
用于判断传进来的对象是否为 null
public boolean isPresent() {
return value != null;
}
3.2、ifPresent()
ifPresent
用于传进来的对象不为null时,则执行后续的函数式接口操作。
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
}
Consumer<? super T> consumer 即为函数式接口的标准写法,Lambda表达式是函数式编程的体现,这里用于接收Lambda表达式。后续对 Lambda表达式进行一番整理。
3.3、filter()
filter
对对象进行过滤,如果对象为空直接返回,如果不满足条件返回空的 Optional 。
public Optional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(value) ? this : empty();
}
3.4、map() 与flatMap()
map()
方法类似于 Stream
中的 map()
方法,从对象中取出特定的属性值,组成一个新的Optional。
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Optional.ofNullable(mapper.apply(value));
}
}
//返回Optional<T>
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
flatMap
用于对象中包含对象类型的属性的场景,例如
public class User implements Serializable {
@ApiModelProperty(value = "主键ID")
@TableId(value = "id", type = IdType.AUTO)
private Long id;
private Optional<Address> address;
}
仔细看下源码,可以发现与 map()
方法存在些许不同
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Objects.requireNonNull(mapper.apply(value));
}
}
//返回T
public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}
执行 flatMap(user -> user.getAddress())
返回的是Optional<Address>
而执行 map(user -> user.getAddress())
返回的是Optional<Optional<Address>>
所以flatMap
常用于 json 字符串的字段判断。
从网上摘抄的例子如下:
需要取得 postcode 字段的值,常规方法是一层层判断很是麻烦,这时可以借用 flatMap
{
"user": {
"age": 20,
"name": "Jim",
"address": {
"province": "浙江省",
"postcode": "111111"
}
}
}
JSONObject jsonObj = JSON.parseObject(json);
String postcode = Optional.ofNullable(jsonObj)
//每进入一层,返回空的Optional或相应的对象
.flatMap(jsonObject -> Optional.ofNullable(jsonObject.getJSONObject("user")))
.flatMap(jsonObject -> Optional.ofNullable(jsonObject.getJSONObject("address")))
.flatMap(jsonObject -> Optional.ofNullable(jsonObject.getString("postcode")))
.orElse("unknown");
System.out.println(postcode);
3.5 orElse()
当对象为 null 时,给予默认值。
public T orElse(T other) {
return value != null ? value : other;
}
3.6 get()
返回对象的值,当对象为 null时,抛出异常。
public T get() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}
基本用法如上,对于有不同想法的欢迎指正。
flatmap
json例子来自文章:https://blog.csdn.net/thc1987/article/details/103005587