optional转化为set_Java8 中的Optional类详解

在Java8中,引入了一个新的类java.util.Optional 。这个类专门用来解决空引用的问题。有了它,对于一个方法的返回值什么的,都不需要再判断是不是null了。同时,这个类和lambda表达式和函数式编程也可以比较好的整合在一起使用。

这里就来看一下这个类的使用。

知道Scala的同学可以类比一下 scala.Option[T] ,或者Haskell的Data.Maybe。都有类似的功能。

Optional是一个容器,里面放着我们的返回值(就是真正要用的东西),但是这个真正要用的东西可能是null呀,所以每次都要判断,但是Optional不可能是null。所以不要在判断是否为null了。

public void print(String s) {

System.out.println(s);

}

String x = //...

Optional opt = //...

上面代码中,x可能是null,opt不可能是null。

建立Optional对象

首先让我们来看一下如何构造Optional对象。Optional对象有一系列静态工厂方法创建出来。

opt = Optional.of(notNull);

opt = Optional.ofNullable(mayBeNull);

opt = Optional.empty();

以上3个方法,第一个of()从一个非null的对象创建Optional,如果传给他null,就有异常NullPointerException。

ofNullable()可以由任意对象(包括null)创建Optional。empty方法总是返回一个空的Optional。

ifPresent()方法:真的存在吗?

Optional在使用的时候,有一些主要的方法,首先是ifPresent。顾名思义,即使对象是否存在的意思。就是说里面装的东西是不是null,这个和判断对象是否为null基本上也是等价的。

if (x != null) {

print(x);

}

以上代码等价于,下面的任何一句话。

opt.ifPresent(x -> print(x));

opt.ifPresent(this::print);

filter()方法:过滤一下吧

另外一个方法是filter()。就是可以做一些条件判断,判断Optional里面的东西,是否满足某一个条件,满足了,就可以做一些额外的操作。

if (x != null && x.contains("ab")) {

print(x);

}

等价于:

opt.

filter(x -> x.contains("ab")).

ifPresent(this::print);

如果不喜欢这种函数式的风格,也可以这么写,更好懂:

if(opt.isPresent() && opt.get().contains("ab")) {

print(opt.get());

}

上面的get()方法就是把Optional的东西拿出来了。

map()方法:执行一些操作

map()方法可以对值做一些处理,将一个操作作用于里面的东西。比如,字符串去掉首尾空格后打印出来:

if (x != null) {

String t = x.trim();

if (t.length() > 1) {

print(t);

}

}

等价于:

opt.

map(String::trim).

filter(t -> t.length() > 1).

ifPresent(this::print);

map()方法会对Optional里的内容做处理,但如果Optional里的是null,他什么都不做(不会有异常哦),只返回empty。

map()还有一个特点是,它是类型安全的。

Optional  opt = //...

Optional len = opt.map(String::length);

一个String的Optional,取出他们的长度,变成了Integer。map()之后的数据类型就是Integer了。

orElse()/orElseGet() 需要一个默认值吗?

如果你在拿到Optional的数据后,发现是他null,你想做一些默认的返回值,执行类似下面的操作:

int len = (x != null)? x.length() : -1;

可以这么写:

int len = opt.map(String::length).orElse(-1);

如果默认值需要被动态计算出来,就是可以用orElseGet(),它接受一个Supplier:

int len = opt.

map(String::length).

orElseGet(() -> slowDefault());     //orElseGet(this::slowDefault)

flatMap() 不会有Null的map

flatMap()方法和map()类似,不同点是,map可以返回任意类型,系统会自动包装为Optional,但是flatMap必须返回Optional,系统不会自动做包装。

//返回值是Optional

public Optional tryFindSimilar(String s)

Optional similar =       opt.flatMap(this::tryFindSimilar);

orElseThrow() 如果值不存在,抛一个异常吧!

以下代码等价,一看便知:

public char firstChar(String s) {

if (s != null && !s.isEmpty())

return s.charAt(0);

else

throw new IllegalArgumentException();

}

opt.

filter(s -> !s.isEmpty()).

map(s -> s.charAt(0)).

orElseThrow(IllegalArgumentException::new);

实例展示

假如有一个Person 对象,它有一个Address 属性,而Address属性还嵌套一个validFrom的日期。所有的值都可能是null。

好了,现在我们来判断一下Person 的这些属性是否是Valid的。

private boolean validAddress(NullPerson person) {

if (person != null) {

if (person.getAddress() != null) {

final Instant validFrom = person.getAddress().getValidFrom();

return validFrom != null && validFrom.isBefore(now());

} else

return false;

} else

return false;

}

或者也可以这么写:

return person != null &&

person.getAddress() != null &&

person.getAddress().getValidFrom() != null &&

person.getAddress().getValidFrom().isBefore(now());

总之 都不是很好看。

但如果这些属性都是Optional,那么看起来会稍微舒服一点。

class Person {

private final Optional

 address;

public Optional

 getAddress() {

return address;

}

//...

}

class Address {

private final Optional validFrom;

public Optional getValidFrom() {

return validFrom;

}

//...

}

以下代码就实现了一样的判断:

return person.

flatMap(Person::getAddress).

flatMap(Address::getValidFrom).

filter(x -> x.before(now())).

isPresent();

使用Optional以后,NullPointerException 就从此消失了。

将一个Optional转为List或者Set

Optional是一个集合,虽然里面只有0或者1个元素,但它一样是一个集合。如果要转为List或者Set,一般的写法可以是:

public static  List toList(Optional option) {

return option.

map(Collections::singletonList).

orElse(Collections.emptyList());

}

或者更传统的写法:

public static  List toList(Optional option) {

if (option.isPresent())

return Collections.singletonList(option.get());

else

return Collections.emptyList();

}

但是在java8里,其实只需要这么写:

import static java.util.stream.Collectors.*;

//转为List

List list = collect(opt, toList());

//转为Set

Set  set  = collect(opt, toSet());

本文代码内容来自于:http://www.nurkiewicz.com/2013/08/optional-in-java-8-cheat-sheet.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值