首页 > 编程语言 >java中Optional的应用,以及map和flatMap的区别

java中Optional的应用,以及map和flatMap的区别

时间:2024-06-22 14:43:01浏览次数:14  
标签:map flatMap return name java Optional public String

关于Option的介绍可以看深入理解java8中的Optional 类就可以了,但是复杂一点的使用在网上却没有搜到,这里结合我开发时遇到的真实案例来讲一下Option的使用。

1.案例一
在真实业务操作过程中,都是对象里面套对象,这边先简单定义操作对象:

public class PictureCondition {
private String url;

public String getUrl() {
    return url;
}

public void setUrl(String url) {
    this.url = url;
}

}
在这里先一个简单的对象,里面也就只有一个属性,在Controller层需要接收一个PictureCondition的对象,应判断这个对象里面的url属性是否为空,或者是有空格出现,如果有的话,则抛出一个异常。

  使用一般的写法是这样判断的:

if(pictureConditionnull||pictureCondition.getUrl()null||"".equals(pictureCondition.getUrl().trim())){
throw new RuntimeException("出错啦");
}
使用Option的写法是这样的:

Optional.ofNullable(pictureCondition)
.map(PictureCondition::getUrl)
.map(String::trim)
.filter(x -> !"".equals(x))
.orElseThrow(() -> new RuntimeException("出错啦"));
对于单层循环使用一般的写法还是可以应对的,但是当层数比较多时,这样写就不太好了。

2.案例二
先定义操作对象

1.定义User对象

public class User {
//用户名称
private String username;

//当前用户的订单信息
private List<Order> orders;

public String getUsername() {
    return username;
}

public void setUsername(String username) {
    this.username = username;
}

public List<Order> getOrders() {
    return orders;
}

public void setOrders(List<Order> orders) {
    this.orders = orders;
}

}
2.定义订单对象

public class Order {
//订单id
private Long orderId;

//订单时间
private Date createTime;

public Long getOrderId() {
    return orderId;
}

public void setOrderId(Long orderId) {
    this.orderId = orderId;
}

public Date getCreateTime() {
    return createTime;
}

public void setCreateTime(Date createTime) {
    this.createTime = createTime;
}

}
具体场景:

    当在一个方法里面需要拿到user对象(可能为空)里面是的orders对象,如果当前orders对象为空,则返回一个空的list对象。

写法:

    Java8之前的写法,我们需要先判断user对象是否为null,不为空的话,获取当orders对象是否为空,为空则返回一个空的list

if(user!=null && user.getOrders!=null) {
return user.getOrders();
} else {
return Collections.emptyList();
}
使用Java8的写法,那么就不需要这样判断了,直接看代码:

return Optional.ofNullable(user)
.map(u -> u.getOrders())
.orElse(Collections.emptyList())
扩展思考:

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

return Optional.ofNullable(user)
.map(u -> u.getUsername())
.map(name -> name.toUpperCase())
.orElse(null);
这要搁在以前, 每一级调用的展开都需要放一个 null 值的判断

User user = .....
if(user != null) {
String name = user.getUsername();
if(name != null) {
return name.toUpperCase();
} else {
return null;
}
} else {
return null;
}
3.Optional中的map和flatMap的区别
源码:

map会将传入的Function函数的结果进行封装,先看源码:

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的ofNullable方法包装Function函数返回的值
    }
}

flatMap会直接返回Function函数执行的结果,看源码:

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));//直接返回Function执行的结果
    }
}
  这样看,好像也看不出来两者太大的区别,不知道什么时候用map,什么时候用flatMap,通过下面的案例进行具体分析

map和flatMap的用法区别

首先对于下列对象的操作

public class School {
private String name;
private Optional tearch; //属性为Option封装的Tearch对象

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public Optional<Tearch> getTearch() {
    return tearch;
}

public void setTearch(Optional<Tearch> tearch) {
    this.tearch = tearch;
}

}

class Tearch{
private String name;
private Optional student;

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public Optional<Student> getStudent() {
    return student;
}

public void setStudent(Optional<Student> student) {
    this.student = student;
}

}

class Student{
private String name;
private int age;

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public int getAge() {
    return age;
}

public void setAge(int age) {
    this.age = age;
}

}
这时,如果给你一个School对象,让你得到Student的name属性的值,可以使用下面的方式:

public static String getStudentName(School school){
return Optional.ofNullable(school)
.map(School::getTearch)
.map(Tearch::getStudent)
.map(Student::getName)
.orElse("false");
}
你可能感觉这样写很对啊,没毛病,可惜这段代码连编译都不会通过的,我们思考一下,School::getTearch会返回School实例的tearch属性,而tearch属性是使用Optional包装的Tearch对象,所以使用了map(School::getTearch),会返回Optional<Optional>对象,而不是我们所想的Optional,这是你可能想自己试一下,我已经做了截图,毕竟有图有真相。

这时就可以使用flatMap来解决这个问题,刚才已经说了,flatMap不会使用Optional包装Function执行的返回结果,所以我们可以使用flatMap来解决这个问题。

public static String getStudentName(School school){
    return Optional.ofNullable(school)
            .flatMap(School::getTearch)
            .flatMap(Tearch::getStudent)
            .map(Student::getName).orElse("false");
}

看截图:

   这时map和flatMap的用法就清楚,如果某对象实例的属性本身就为Optional包装过的类型,那么就要使用flatMap方法,就像School::getTearch返回的就是Optional<Tearch>类型的,所以不用再使用Optional进行包装,这时就要选用flatMap方法,对于返回值是其他类型,需要Optional进行包装,如Student::getName得到是String类型的,就需要使用map方法在其外面包装一层Optional对象。

注意:Option类是判断空指针异常时用的,对于其他的if..else只要不是判断空指针的问题,就不要使用Option类,lz就陷入了一个误区,以为学了Option类,看见if...else就往Option来想,这么做真是大作特错。用Option的情况时在判断值是否为null时,Option就发挥作用了。
————————————————

                        版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/qq_35634181/article/details/101109300

标签:map,flatMap,return,name,java,Optional,public,String
From: https://www.cnblogs.com/huft/p/18262320

相关文章

  • java网络编程 , 网络编程 , Junit单元测试概念及使用方法详细介绍
    网络编程主要内容网络编程TCP通信Junit单元测试1网络编程1.1软件架构C/S结构:全称为Client/Server结构,是指客户端和服务器结构。常见程序有QQ、迅雷等软件B/S结构:全称为Browser/Server结构,是指浏览器和服务器结构。常见浏览器有谷歌、火狐等两种架构各有优势,但......
  • java单例设计模式 , 多例设计模式 , 工厂设计模式概念及详细介绍
    单例设计模式正常情况下一个类可以创建多个对象publicstaticvoidmain(String[]args){ //正常情况下一个类可以创建多个对象 Personp1=newPerson(); Personp2=newPerson(); Personp3=newPerson();}如果说有时一个对象就能搞定的事情,非要创建多......
  • Java 接口
    本篇学习接口,并区分接口与抽象类两者之间的异同点。上篇已经讲解了抽象类,有需要的小伙伴可以点链接康康https://blog.csdn.net/m0_73107796/article/details/139863674目录1、什么是接口2、接口定义格式3、接口的使用 4、接口特性5、抽象类与接口的区别 1、什......
  • DVWA 靶场 JavaScript 通关解析
    前言DVWA代表DamnVulnerableWebApplication,是一个用于学习和练习Web应用程序漏洞的开源漏洞应用程序。它被设计成一个易于安装和配置的漏洞应用程序,旨在帮助安全专业人员和爱好者了解和熟悉不同类型的Web应用程序漏洞。DVWA提供了一系列的漏洞场景和练习环境,用户可以通过......
  • .Net开发 ,Java开发 ,python开发 数据库开发,开发相关工具
    开发电脑安装相关工具软件Java开发Java编程、高级编程、面试题资料Python编程,网络编程,爬虫,面试,设计资料数据库mysql,sqlservice,sql优化资料C#语言、.Net开发、.Net高级编程资料......
  • Java 8 Stream
    Java8StreamJava8新特性Java8新特性Java8API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。Stream使用一种类似用SQL语句从数据库查询数据的直观方式来提供一种对Java集合运算和表达的高阶抽象。StreamAPI可以极大提高Java程序员的生产力,......
  • java多线程编程问题以及解决办法
    java多线程编程问题以及解决办法  多线程编程虽然可以提高程序的性能和响应速度,但也带来了许多复杂的问题,如竞态条件、死锁、线程安全问题、内存一致性错误等。常用的解决方法包括使用同步机制(如synchronized和ReentrantLock)、线程池、volatile关键字、以及合适的线程间......
  • 【JavaScript脚本宇宙】终极对决:六大虚拟DOM库横评
    深度剖析:六大虚拟DOM库的奥秘与应用场景前言虚拟DOM(DocumentObjectModel)是用于表示和操作HTML文档的抽象数据结构。虚拟DOM库是构建用户界面的重要工具,它们提供了高效的更新机制、组件化开发等功能,使开发者能够轻松地开发高性能、可维护的Web应用程序。本文将介绍几个流......
  • 基于javaweb房产中介房屋租赁系统设计与实现
      博主介绍:黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育和辅导。所有项目都配有从入门到精通的基础知识视频课程,学习后应对毕业设计答辩。项目配有对应开发文档、开题报告、任务书......
  • Java计算机毕业设计博物馆管理系统(开题报告+源码+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着信息技术的飞速发展,传统博物馆的管理模式已经难以适应现代社会的需求。博物馆作为重要的文化传承和展示机构,需要更加高效、智能的管理系统来支撑......