java8 optional

188 阅读2分钟

一、初始化

1、private Optional(T value)

私有化构造方法入参为空时抛空指针异常。

private Optional(T value) {
    this.value = Objects.requireNonNull(value);
}

2、Optional.of(T value) 就是调用私有化构造方法

  public static <T> Optional<T> of(T value) {
        return new Optional<>(value);
    }

3、Optional.ofNullable(T value)入参为空时构建一个value为null的optional

public static <T> Optional<T> ofNullable(T value) {
        return value == null ? empty() : of(value);
    }

4、Optional.empty() 构建一个value为null的optional

二、取值

1、Optional.get()

值为null抛异常,否值返回值。

 public T get() {
        if (value == null) {
            throw new NoSuchElementException("No value present");
        }
        return value;
    }

2、orElse(T t)

如果调用对象包含值,返回该值,否则返回t(默认值)。

public T orElse(T other) {
    return value != null ? value : other;
}

3、orElseGet(Supplier s)

如果调用对象包含值,返回该值,否则返回 s 获取的值。

public T orElseGet(Supplier<? extends T> other) {
    return value != null ? value : other.get();
}

4、orElseThrow()

它会在对象为空的时候抛出指定异常。

public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
    if (value != null) {
        return value;
    } else {
        throw exceptionSupplier.get();
    }
}

三、判断

1、isPresent

判断value值是否为空

public boolean isPresent() {
    return value != null;
}

2、ifPresent

非空执行

public void ifPresent(Consumer<? super T> consumer) {
    if (value != null)
        consumer.accept(value);
}

四、数据处理

1、map

非飞空的value数据进行处理。

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));
    }
}

demo:

User user = getUserFromSomewhere();
if (user != null) {
    Address address = user.getAddress();
    if (address != null) {
        String city = address.getCity();
        if (city != null) {
            System.out.println(city);
        } else {
            System.out.println("City not found.");
        }
    } else {
        System.out.println("Address not found.");
    }
} else {
    System.out.println("User not found.");
}

转换后

Optional<User> optionalUser = Optional.ofNullable(getUserFromSomewhere());
optionalUser.map(User::getAddress)
        .map(Address::getCity)
        .ifPresent(System.out::println);
optionalUser.map(User::getAddress)
        .map(Address::getCity)
        .orElse("City not found.");

2、flatMap

flatMap 方法与 map 方法的区别在于,map 方法参数中的函数 mapper 输出的是值,然后 map 方法会使用 Optional.ofNullable 将其包装为 Optional;而 flatMap 要求参数中的函数 mapper 输出的就是 Optional

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));
    }
}

五、使用示例

1、例一

以前写法

public String getCity(User user)  throws Exception{
    if(user!=null){
      if(user.getAddress()!=null){
        Address address = user.getAddress();
        if(address.getCity()!=null){
          return address.getCity();
        }
      }
    }
    throw new Excpetion("取值错误"); 
  }

JAVA8写法

public String getCity(User user) throws Exception{
  return Optional.ofNullable(user)
           .map(u-> u.getAddress())
           .map(a->a.getCity())
           .orElseThrow(()->new Exception("取指错误"));
}

2、例二

比如,在主程序中 以前写法

if(user!=null){
  dosomething(user);
}

JAVA8写法

public User getUser(User user) {
  return Optional.ofNullable(user)
                 .filter(u->"zhangsan".equals(u.getName()))
                 .orElseGet(()-> {
                    User user1 = new User();
                    user1.setName("zhangsan");
                    return user1;
                 });
}

3、例三

当 user.isPresent() 为真, 获得它关联的 orders的映射集合, 为假则返回一个空集合时, 我们用上面的 orElse, orElseGet 方法都乏力时, 那原本就是 map 函数的责任, 我们可以这样一行:

return user.map(u -> u.getOrders()).orElse(Collections.emptyList())
 
//上面避免了我们类似 Java 8 之前的做法
if(user.isPresent()) {
  return user.get().getOrders();
} else {
  return Collections.emptyList();
}

map 是可能无限级联的, 比如再深一层, 获得用户名的大写形式:

return user.map(u -> u.getUsername())
           .map(name -> name.toUpperCase())
           .orElse(null);

以前的做法:

User user = .....
if(user != null) {
  String name = user.getUsername();
  if(name != null) {
    return name.toUpperCase();
  } else {
    return null;
  }
} else {
  return null;
}

filter() :如果有值并且满足条件返回包含该值的Optional,否则返回空Optional。

Optional<String> longName = name.filter((value) -> value.length() > 6);  
System.out.println(longName.orElse("The name is less than 6 characters"));