Optional的简单理解

Optional的简单理解

在上篇博客简单讲解了 Stream 的基本用法,Stream的许多终端操作返回类型为 Optional 类型,第一次见到这个类型,看了源码及网上的资料有了简单的理解。

image-20201201161127285

1、Optional 介绍

Optional 是 JDK8 新增的一个类,看了下源码,可以知道 Optional 是一个用来存储对象的辅助类,可以判断对象是否为空并进行后续操作。

image-20201201162644689

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

自我控制是最强者的本能-萧伯纳
原文地址:https://www.cnblogs.com/CF1314/p/14069850.html