optional判断是否为空_Java8新特性_Optional
一、Optional介绍java.util.Optional是一个Java JDK8引入的类,借鉴了Google Guava工具包的Optional类,其目的是为了避免空指针问题(java.lang.NullPointerException)。Optional是一个容器类,它可以存放空值或非空值对象,通过函数式方法进行判断、过滤和映射等操作,对空值进行处理并返回Optional对象。二、实例方法1
一、Optional介绍
java.util.Optional
是一个Java JDK8引入的类,借鉴了Google Guava工具包的Optional类,其目的是为了避免空指针问题(java.lang.NullPointerException)。
Optional
是一个容器类,它可以存放空值或非空值对象,通过函数式方法进行判断、过滤和映射等操作,对空值进行处理并返回Optional对象。
二、实例方法
1、empty
empty
,直接创建一个EMPTY实例,空值的Optional对象。
/**
* Common instance for {@code empty()}.
*/
private static final Optional<?> EMPTY = new Optional<>();
/**
* Returns an empty {@code Optional} instance. No value is present for this
* Optional.
*/
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
仔细查看源码,EMPTY参数直接指向一个Optional对象,如果去掉了final修饰符,看起来不就是懒汉式单例吗,于是有了以下的测试用例。
该功能就表明,我们可以使用==和Optional.empty()比较,就可以判断出对象是不是为空,从而避开空指针问题。当然也可以使用isPresent()方法,同样可以实现判断空值的效果。
public static void main(String[] args) {
PersonEntity person = null;
Optional optional1 = Optional.ofNullable(person);
Optional optional2 = Optional.empty();
// 返回结果:true
System.out.println(optional1 == optional2);
}
2、of
of
,创建一个不为空值的Optional对象,如果传入空值会报NullPointerException。
/**
* Returns an {@code Optional} with the specified present non-null value.
*/
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
3、ofNullable
ofNullable
,创建一个可空值也可非空值的Optional对象,当不确定value值是否为空时可以使用。
通过源码可以分析,value为空值使用empty()方法,为非空值使用of()方法。
/**
* Returns an {@code Optional} describing the specified value, if non-null,
* otherwise returns an empty {@code Optional}.
*/
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
三、获取value
1、get
get
,获取Optional对象的value值,如果value为EMPTY
,那会抛出NoSuchElementException异常。
所以使用该方法前,最好使用isPresent()
方法判断是否为空。
/**
* If a value is present in this {@code Optional}, returns the value,
* otherwise throws {@code NoSuchElementException}.
*/
public T get() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}
// 测试用例
public static void main(String[] args) {
PersonEntity person = new PersonEntity("张三", 18);
Optional optional = Optional.ofNullable(person);
System.out.println(optional.get());
/*
* 返回结果:PersonEntity(name=张三, age=18)
*/
PersonEntity person2 = null;
Optional optional2 = Optional.ofNullable(person2);
System.out.println(optional2.get());
/*
* 抛异常:java.util.NoSuchElementException: No value present
*/
}
2、orElse
orElse
,获取Optional对象的value值,如果value为EMPTY
,则返回other对象,相当于为空值判断而设置默认对象。
/**
* Return the value if present, otherwise return {@code other}.
*/
public T orElse(T other) {
return value != null ? value : other;
}
// 测试用例
public static void main(String[] args) {
PersonEntity defaultPerson = new PersonEntity("李四", 15);
PersonEntity person = null;
Optional optional = Optional.ofNullable(person);
System.out.println(optional.orElseGet(defaultPerson));
/*
* 返回结果:PersonEntity(name=李四, age=15)
*/
}
3、orElseGet
orElseGet
,获取Optional对象的value值,如果value为EMPTY
,则使用Supplier供给型接口来获取默认值。
/**
* Return the value if present, otherwise invoke {@code other} and return
* the result of that invocation.
*/
public T orElseGet(Supplier<? extends T> other) {
return value != null ? value : other.get();
}
// 测试用例
public static void main(String[] args) {
PersonEntity person = null;
Optional<PersonEntity> optional = Optional.ofNullable(person);
System.out.println(optional.orElseGet(() -> new PersonEntity("王五", 20)));
/*
* 返回结果:PersonEntity(name=王五, age=20)
*/
}
4、orElseThrow
orElseThrow
,获取Optional对象的value值,如果value为EMPTY
,则使用Supplier供给型接口来创建抛出异常。
/**
* Return the contained value, if present, otherwise throw an exception
* to be created by the provided supplier.
*/
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (value != null) {
return value;
} else {
throw exceptionSupplier.get();
}
}
public static void main(String[] args) {
PersonEntity person = null;
Optional<PersonEntity> optional = Optional.ofNullable(person);
System.out.println(optional.orElseThrow(() -> new RuntimeException("this value is null")));
/*
* 抛异常:java.lang.RuntimeException: this value is null
*/
}
四、判断是否存在
1、isPresent
isPresent
,判断Optional的value是否为EMPTY
,为空值返回false,不为空值返回true。
/**
* Return {@code true} if there is a value present, otherwise {@code false}.
*/
public boolean isPresent() {
return value != null;
}
// 测试用例
public static void main(String[] args) {
PersonEntity person = null;
Optional<PersonEntity> optional = Optional.ofNullable(person);
System.out.println(optional.isPresent());
/*
* 返回结果:false
*/
PersonEntity person2 = new PersonEntity("刘六", 21);
Optional<PersonEntity> optional2 = Optional.ofNullable(person2);
System.out.println(optional2.isPresent());
/*
* 返回结果:true
*/
}
2、ifPresent
ifPresent
,判断Optional的value是否为EMPTY
,不为空值则调用Consumer消费型接口的accept方法,否则什么都不做。
/**
* If a value is present, invoke the specified consumer with the value,
* otherwise do nothing.
*/
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
}
// 测试用例
public static void main(String[] args) {
PersonEntity person = new PersonEntity("秦七", 21);
Optional<PersonEntity> optional = Optional.ofNullable(person);
optional.ifPresent(System.out::println);
/*
* 返回结果:PersonEntity(name=秦七, age=21)
*/
PersonEntity person2 = new null;
Optional<PersonEntity> optional2 = Optional.ofNullable(person2);
optional2.ifPresent(System.out::println);
/*
* 返回结果:
*/
}
五、判断是否相等
1、equals
equals
,比较两个Optional对象,指向地址相同为true,不是Optional对象为false,然后在比较两者的value值。
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Optional)) {
return false;
}
Optional<?> other = (Optional<?>) obj;
return Objects.equals(value, other.value);
}
2、hashCode
hashCode
,获取该Optional对象的hashCode,如果value值为空返回0,不为空则返回Obejct.hashCode()。
如果两个Optional对象的value值相同,那他们的hashCode也是相同。
@Override
public int hashCode() {
return Objects.hashCode(value);
}
// Objects.hashCode()方法
public static int hashCode(Object o) {
return o != null ? o.hashCode() : 0;
}
六、其他lambda表达式
1、filter
filter
,判断Optional的value是否为EMPTY
,不为空值且满足Predicate断言型接口则返回该Optional对象,其他情况均返回空Optional对象。
/**
* If a value is present, and the value matches the given predicate,
* return an {@code Optional} describing the value, otherwise return an
* empty {@code Optional}.
*/
public Optional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(value) ? this : empty();
}
// 测试用例
public static void main(String[] args) {
PersonEntity person = new PersonEntity("赵八", 28);
Optional<PersonEntity> optional = Optional.ofNullable(person);
System.out.println(optional.filter(p -> p.getAge() > 15));
/*
* 返回结果:PersonEntity(name=赵八, age=28)
*/
PersonEntity person2 = new PersonEntity("赵八2", 10);
Optional<PersonEntity> optional2 = Optional.ofNullable(person2);
System.out.println(optional2.filter(p -> p.getAge() > 15));
/*
* 返回结果:Optional.empty
*/
}
2、map
map
,判断Optional的value是否为EMPTY
,不为空值就调用Function函数型接口,如果结果不为空则返回包含该结果的Optional对象,其他情况均返回空Optional对象。
/**
* If a value is present, apply the provided mapping function to it,
* and if the result is non-null, return an {@code Optional} describing the
* result. Otherwise return an empty {@code 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));
}
}
public static void main(String[] args) {
PersonEntity person = new PersonEntity("牛九", 21, null);
Optional<PersonEntity> optional = Optional.ofNullable(person);
System.out.println(optional.map(PersonEntity::getName));
/*
* 返回结果:Optional[牛九]
*/
PersonEntity person2 = null;
Optional<PersonEntity> optional2 = Optional.ofNullable(person2);
System.out.println(optional2.map(PersonEntity::getName));
/*
* 返回结果:Optional.empty
*/
}
3、flatMap
flatMap
,判断Optional的value是否为EMPTY
,不为空值就调用Function函数型接口,如果结果不为空则返回Optional类型返回值,其他情况均返回空Optional对象。
/**
* If a value is present, apply the provided {@code Optional}-bearing
* mapping function to it, return that result, otherwise return an empty
* {@code Optional}. This method is similar to {@link #map(Function)},
* but the provided mapper is one whose result is already an {@code Optional},
* and if invoked, {@code flatMap} does not wrap it with an additional
* {@code 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));
}
}
public static void main(String[] args) {
PersonEntity person = new PersonEntity("石十", 21, null);
Optional<PersonEntity> optional = Optional.ofNullable(person);
System.out.println(optional.flatMap(p -> Optional.ofNullable(p.getName())));
/*
* 返回结果:Optional[石十]
*/
PersonEntity person2 = null;
Optional<PersonEntity> optional2 = Optional.ofNullable(person2);
System.out.println(optional2.flatMap(p -> Optional.ofNullable(p.getName())));
/*
* 返回结果:Optional.empty
*/
}
map
和flatMap
区别:
方法名 | map | flatMap |
---|---|---|
方法参数 | Function<? super T, ? extend U>mapper | Function<? super T, Optional<U>> mapper |
mapper结果 | U,表示一个普通对象 | Optional,表示Optional对象 |
过程 | 用ofNullable方法包装U,返回Optional | 直接返回Optional |
七、注意事项
Optional
没有实现Serializable
接口,就意味着它无法被序列化,所以它不应该用作类的字段。- 只有每当结果不确定时,使用
Optional
作为返回类型,从某种意义上讲,这是使用Optional的唯一好地方,用java官方的话讲就是:我们的目的是为库方法的返回类型提供一种有限的机制,其中需要一种明确的方式来表示“无结果”,并且对于这样的方法使用null 绝对可能导致错误。 - 避免使用
Optional.isPresent()
来判断Optional的值是否为空,这种方法和null != obj
没有区别,也就没有意义。 - 避免使用
Optional.get()
来获取实例对象,因为使用前需要调用Optional.isPresent()
来判断,否则会出现NoSuchElementException异常,建议使用orElse()
、orElseGet()
、orElseThrow()
获得结果。
八、案例实践
1、测试用例
人员实体
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PersonEntity {
private String id;
private String name;
private Integer age;
private DogEntity dog;
}
宠物狗实体
@Data
@NoArgsConstructor
@AllArgsConstructor
public class DogEntity {
private String id;
private String name;
private Integer age;
}
伪方法
// 根据id集合获取人员信息
private static List<PersonEntity> selectPerson(List<String> ids) {
return null;
}
// 根据id集合获取宠物狗信息
private static List<DogEntity> selectDot(List<String> ids) {
return null;
}
2、获取宠物狗名称
// 方法一:!=null方法
public static String getDogName1(PersonEntity person) {
if (null != person) {
DogEntity dog = person.getDog();
if (null != dog) {
return dog.getName();
}
}
return "旺财";
}
// 方法二:Optional方法
public static String getDogName2(PersonEntity person) {
return Optional.ofNullable(person)
.map(PersonEntity::getDog)
.map(DogEntity::getName)
.orElse("旺财");
}
3、获取宠物狗名称集合
// 方法一:普通方法
public static List<String> getDogNameList1(List<String> personIds) {
List<String> dogNameList = new ArrayList<>();
List<PersonEntity> personList = selectPerson(personIds);
if (null == personList || 0 == personList.size()) {
return dogNameList;
}
List<String> personNewIds = new ArrayList<>();
for (int i = 0; i < personList.size(); i++) {
if (null != personList.get(i)) {
personNewIds.add(personList.get(i).getName());
}
}
if (null == personNewIds || 0 == personNewIds.size()) {
return dogNameList;
}
List<DogEntity> dogList = selectDot(personNewIds);
for (int i = 0; i < dogList.size(); i++) {
if (null != dogList.get(i)) {
dogNameList.add(dogList.get(i).getName());
}
}
return dogNameList;
}
// 方法二:Optional方法
public static List<String> getDogNameList2(List<String> personIds) {
List<String> dogNameList = Optional.ofNullable(selectPerson(personIds))
.filter(person -> !person.isEmpty())
.map(pList -> selectDot(pList.stream().map(PersonEntity::getId).collect(Collectors.toList())))
.map(dList -> dList.stream().map(DogEntity::getName).collect(Collectors.toList()))
.orElse(new ArrayList<>());
return dogNameList;
}
更多推荐
所有评论(0)