java8 Optional 包装类
一. 概述Optional
Optional 是一个容器类,在java.util.Optional,可以保持类型T的值,并且可以很好的处理空指针问题,例如调用isPresent()方法如果有值的话返回true,调用get()返回包装到T对象,调用orElse()方法返回数据,如果没有返回一个预先设置的对象,调用orElseThrow()如果有值则返回,如果没有值则跑出异常等
二. Optional使用
1. 方法概述
2. 代码示例
@Test
public void test7(){
//创建Option对象
//1.Optional.of(T t) 创建一个Optional 实例,t必须非空
//注意在调用of()静态方法创建Option对象时,若方法中的数据对象为空会跑出异常
Persion persion1 = new Persion();
Optional<Persion> perOptional1 = Optional.of(persion1);
Persion persion2 = null;
//2.Optional.ofNullable(T t) 创建一个Optional实例,方法中的t允许为空
//(在不知道是否真实存在的时候使用)
Optional<Persion> perOptional2 = Optional.ofNullable(persion2);
//3.Option.empty() 创建一个空的Optional实例
Optional emptyOption = Optional.empty();
//判断Optional中是否存在数据
//isPresent(); 存在返回true,
Boolean b = perOptional1.isPresent();
System.out.println(b);
//ifPresent(Consumer<? super T> customer)
//该方法中传递了一个Consumer函数式接口,若调用该方法的Optional
//实例中对象数据真实存在则实现Consumer的方法体
perOptional1.ifPresent(p -> p.setName("小明"));
System.out.println(persion1.getName());
//在Optional实例中获取对象数据
//1.get() 若调用该方法的Optional实例中的对象数据为空则会抛出异常
Persion p = perOptional1.get();
//2.orElse(T other) 如果调用该方法的Optional实例中有则返回,如果没有,则使用方法中传递的这个other
Persion p2 = perOptional2.orElse(new Persion("小红",22,3500.00));
System.out.println(p2.getName());
//3.orElseGet(Supplier<? extends T> other); 如果有值则返回,
//否则返回有Supplier函数式接口提供的对象
//perOptional2.orElseGet(Supplier函数式接口提供的对象);
//4.or ElseThrow(supplier<? extends X> exceptionSupplier);如果有值则返回,
//否则由Supplier函数式接口抛出异常(可以抛出自定义异常)
perOptional2.orElseThrow( () -> new NullPointerException());
}
ifPresent使用示例
private BizResponseData<List<GuestOperationResp.Row>> checkinGuestUpdate(PmsHotelInfoDO pmsHotelInfo, List<GuestOperationResp.Row> existGuestList, GuestOperationReq guestReq) {
//1.根据查询到的客户信息,拿到同名的resGuestId
List<String> resGuestIdList = existGuestList.stream()
.filter(existG -> guestReq.getGuestName().equals(existG.getGuestName()))
.map(GuestOperationResp.Row::getResGuestId)
.collect(Collectors.toList());
//2.如果resGuestId不为空,说明该入住人已存在,Modify执行更新操作,否则执行Add添加操作
guestReq.setOperate(CollectionUtils.isEmpty(resGuestIdList) ? "Add" : "Modify");
//注意如果resGuestIdList为null会报空指针
Optional.of(resGuestIdList)
.filter(l -> !l.isEmpty())
.map(l -> l.get(0))
.ifPresent(guestReq::setResGuestId);
//3.调用三方订单客人资料维护
return this.guestOperationExecute(pmsHotelInfo, guestReq);
}
Optional的 map(), flatMap(), filter(), 集合遍历等
@Test
public void test8() {
Persion persion = new Persion("小明", 22, 2000.00);
//Optional通过map()方法,获取数据
Optional.ofNullable(persion).map(p -> p.getName()).orElse("default@gmail.com");
//flatMap()
//分析Optional实例调用 Optional<T> map(Function<T> f)方法,返回的是一个包含数据的Optional对象
//假设传递给map方法中的数据本身就是一个Optional<Optional<T>>
//这时map和flatMap的用法就清楚,如果某对象实例的属性本身就为Optional包装过的类型,
//那么就要使用flatMap方法,假设p.getName()返回的就是Optional<Persion>类型的,所以不用再使用Optional进行包装,
//过滤 filter() 接收一个Predicate函数式接口类型
Optional<Persion> optPersion = Optional.ofNullable(persion)
.filter( p -> p.getName() != null);
//Optional 集合遍历
List<Persion> persionList = new ArrayList<>();
persionList.add(new Persion("小强", 40, 3500.00));
persionList.add(new Persion("小黑", 22, 2200.00));
persionList.add(new Persion("小花", 27, 2000.00));
persionList.add(new Persion("bb", 16, 1500.00));
persionList.add(new Persion("小明", 22, 2000.00));
List<Persion> pList2 = new ArrayList<>();
Optional.ofNullable(persionList).orElse(new ArrayList<>()).forEach(p -> {
if(p.getSalary()>2500) {
pList2.add(p);
System.out.println(p.getSalary());
}
});
}
遍历示例
- 判空遍历原逻辑
SspUnionPolicyDetailShowResp showResp = new SspUnionPolicyDetailShowResp();
InterestsCell interestsCell2 = null;
if (ObjectUtils.isNotEmpty(showResp)
&& ObjectUtils.isNotEmpty(showResp.getNonCarInfo())
&& ObjectUtils.isNotEmpty(showResp.getNonCarInfo().getInterestsCellList())) {
List<InterestsCell> interestsCellList = showResp.getNonCarInfo().getInterestsCellList();
for (InterestsCell cell : interestsCellList) {
if (ObjectUtils.isNotEmpty(cell) && StringUtils.equalsIgnoreCase("1", cell.getBenefitName())) {
interestsCell2 = cell;
break;
}
}
}
if (ObjectUtils.isNotEmpty(interestsCell2)){
System.out.println(interestsCell2.getBenefitName());
}
- Optional 判空遍历示例
SspUnionPolicyDetailShowResp showResp = new SspUnionPolicyDetailShowResp();
String string = Optional.ofNullable(showResp)
.map(SspUnionPolicyDetailShowResp::getNonCarInfo)
.map(SspNonCarPolicyDetailShowResp::getInterestsCellList)
.map(s -> s.stream().filter(Objects::nonNull)
.filter(s1 -> StringUtils.equalsIgnoreCase("1", s1.getBenefitName()))
.map(InterestsCell::getBenefitName)
.findFirst().orElse(null)
)
.orElse(null);
System.out.println(string);
- 其实第二种代码量并没有少很多,且还不如第一种直观易懂, 使用Optional再次优化修改
public void mapOptionalTest(){
GeneralRenewalPlanVO upgradeRenewalPlanVO = Optional.ofNullable(generalRenewalVO.getGeneralRenewalPlanVOList())
.orElse(new ArrayList<>())
.stream()
.filter(RenewalUpgradeHelper::isUpgradePlan)
.findFirst()
.orElse(null);
GeneralRenewalPlanVO upgradeRenewalPlanVO = Optional.ofNullable(generalRenewalVO.getGeneralRenewalPlanVOList())
.map(list -> list.stream().filter(RenewalUpgradeHelper::isUpgradePlan).findFirst().get())
.orElse(null);
}