【java】Optional操作

参考:

  • 【Java8】 Optional 详解
  • java Optional操作

1、简介

Optional类是Java8为了解决null值判断问题,借鉴google guava类库的Optional类而引入的一个同名Optional类,使用Optional类可以避免显式的null值判断(null的防御性检查),避免null导致的NPE(NullPointerException)。

我们来看一段代码:

public static String getGender(Student student)
{if(null == student){return "Unkown";}return student.getGender();
}

这是一个获取学生性别的方法,方法入参为一个Student对象,为了防止student对象为null, 做了防御性检查:如果值为null,返回"Unkown"。
再看使用Optional优化后的方法:

public static String getGender(Student student)
{return Optional.ofNullable(student).map(u -> u.getGender()).orElse("Unkown");
}

可以看到,Optional类结合lambda表达式的使用能够让开发出的代码更简洁和优雅。

2、、Optional对象的创建

// 1、创建一个包装对象值为空的Optional对象
Optional<String> optStr = Optional.empty();// 2、创建包装对象值非空的Optional对象
Optional<String> optStr1 = Optional.of("optional");// 3、创建包装对象值允许为空的Optional对象
Optional<String> optStr2 = Optional.ofNullable(null);

(1)of创建

Student student = new Student("王五", 80);
Optional<Student> optional = Optional.of(student);

(2)ofNullable创建

Student student = new Student("王五", 80);
Optional<Student> optional = Optional.ofNullable(student);

(3)of 和 ofNullable区别

  • of:接收的值不能为 null,否则会报空指针异常
  • ofNullable:接收的值可以是 null,不会报空指针异常,但如果接收的值是是 null,在使用 get() 获取的时候就会报空指针
Student student = null;
//of 里只要传的参数只要是 null,就会报空指针异常
Optional<Student> optional = Optional.of(student);Student student = null;
//ofNullable 接收的值可以为 null 
Optional<Student> optional = Optional.ofNullable(student);
//如果上面ofNullable 里接收的值 为 null ,下面使用 get() 获取对象会报空指针异常
Student student1 = optional.get();

3、判空处理

(1)isPresent()

功能:判断非空,isPresent 相当于 !=null

Student student1 = new Student("王五", 80);
Optional<Student> optional = Optional.ofNullable(student1);
//将输出:student1不为空的操作
if (optional.isPresent()){System.out.println("student1不为空的操作");
}else {System.out.println("student1为空的操作");
}Student student2 = null;
Optional<Student> optional2 = Optional.ofNullable(student2);
//将输出:student2为空的操作
if (optional2.isPresent()){System.out.println("student2不为空的操作");
}else {System.out.println("student2为空的操作");
}

(2)isEmpty()

功能:判断为空,isEmpty 相当于 ==null,Java 11 开始,我们可以使用 isEmpty 方法来处理相反的操作

Student student1 = new Student("王五", 80);
Optional<Student> optional = Optional.ofNullable(student1);
//将输出:student1不为空的操作
if (optional.isEmpty()){System.out.println("student1为空的操作");
}else {System.out.println("student1不为空的操作");
}Student student2 = null;
Optional<Student> optional2 = Optional.ofNullable(student2);
//将输出:student2为空的操作
if (optional2.isEmpty()){System.out.println("student2为空的操作");
}else {System.out.println("student2不为空的操作");
}

4、条件动作

(1)ifPresent()

功能:相当于判断 !=null , 不为空才执行里面的代码

Student student1 = new Student("王五", 80);
Optional<Student> optional = Optional.ofNullable(student1);optional.ifPresent(student -> System.out.println("student1不为空,姓名为:"+student.getName()));

(2)ifPresentOrElse()

功能:java 9里新增了 ifPresentOrElse(),当 Optional 里的值不为空则执行第一个参数里的代码,为空则执行第二个参数的代码,相当于 if-else

Student student = new Student("王五", 80);
Optional<Student> optional = Optional.ofNullable(student);optional.ifPresentOrElse(value -> System.out.println("student不为空,姓名:"+value.getName()), () -> System.out.println("student为空") );

5、get()获取值

功能:返回包装对象的实际值,但是如果包装对象值为null,会抛出NoSuchElementException异常

示例:

需要注意的是如果 student1 为 null,在使用 get() 获取值的时候会抛出 NoSuchElementException 异常:

(下面的写法只是样例,并不可取,后面会有几种代替 isPresent()和 get() )

Student student1 = new Student("王五", 80);
Optional<Student> optional = Optional.ofNullable(student1);
Student myStudent = optional.get();
System.out.println("姓名:"+myStudent.getName());//输出姓名:王五

使用以下写法替代上面

Student student1 = null;
Optional<Student> optional = Optional.ofNullable(student1);if (optional.isPresent()){Student myStudent = optional.get();System.out.println("姓名:"+myStudent.getName());
}else {System.out.println("student1为空");
}

6、orElse()/orElseGet()/orElseThrow()

(1)orElse()

功能:orElse()方法功能比较简单,即如果包装对象值非空,返回包装对象值,否则返回入参other的值(默认值)

示例:

String gender = Optional.ofNullable(student).map(u -> u.getGender()).orElse("Unkown");

(2)orElseGet()

orElse 与 orElseGet 可替代 get 操作并且可以避免 get 操作出现的NoSuchElementException 异常

使用 orElse:

Student student1 = new Student("王五", 80);
Student student2 = new Student("张三", 90);
Optional<Student> optional = Optional.ofNullable(student1);//先执行orElse里的语句,然后判断student1不为空则返回student1给 student3,否则返回student2给student3
Student student3 = optional.orElse(student2);

使用 orElseGet:

Student student1 = new Student("王五", 80);
Student student2 = new Student("张三", 90);
Optional<Student> optional = Optional.ofNullable(student1);//判断student1不为空则返回student1给 student3,否则返回student2给student3
Student student3 = optional.orElseGet(()->student2);

orElse与orElseGet区别

  • 无论 Optional 中的值是否为空 orElse 中的代码都会执行,而 orElseGet 中的代码只有 Optional 中的值为空才会执行。
  • orElseGet 接收的是 Supplier 类型的参数,而 orElse 接受的是T类型的参数;
    当 student1 为空时 orElse 和 orElseGet 都会执行:
public static void main(String[] args) throws Exception {Student student1 = null;Optional<Student> optional = Optional.ofNullable(student1);Student student2 = optional.orElse(getMyStudent());Student student3 = optional.orElseGet(() -> getMyStudent());
}public static Student getMyStudent() {System.out.println("开始执行getMyStudent");return new Student("张三", 90);
}

当 student1 不为空时只有 orElse 会执行:

public static void main(String[] args) throws Exception {Student student1 =  new Student("王五", 80);Optional<Student> optional = Optional.ofNullable(student1);Student student2 = optional.orElse(getMyStudent());Student student3 = optional.orElseGet(() -> getMyStudent());
}public static Student getMyStudent() {System.out.println("开始执行getMyStudent");return new Student("张三", 90);
}

(3)orElseThrow()

**功能:**orElseThrow()方法其实与orElseGet()方法非常相似了,入参都是Supplier对象,只不过orElseThrow()的Supplier对象必须返回一个Throwable异常,并在orElseThrow()中将异常抛出

String gender = Optional.ofNullable(student).map(u -> u.getGender()).orElseThrow(() -> new RuntimeException("Unkown"));

7、or()

Java 9引入了 or() 方法,or 操作与 orElse 和 orElseGet 操作相似,只不过 or 操作返回的是一个新的Optional 对象,而 orElse 和 orElseGet 操作返回的是 Optional 中的值

String expected = null;
Optional<String> value = Optional.ofNullable(expected);
Optional<String> defaultValue = Optional.of("default");//or()方法将返回一个新的Optional对象
Optional<String> result = value.or(() -> defaultValue);
System.out.println(result.get());//default

8、filter()过滤

filter 将谓词作为参数并返回一个 Optional 对象

Integer year = 2022;
Optional<Integer> yearOptional = Optional.ofNullable(year);boolean is2022 = yearOptional.filter(y -> y == 2016).isPresent();
System.out.println(is2022);//true
boolean is2023 = yearOptional.filter(y -> y == 2017).isPresent();
System.out.println(is2023);//false

9、map()转化值

功能:map()方法将Optional中的包装对象用Function函数进行运算,并包装成新的Optional对象(包装对象的类型可能改变)

示例:

先用ofNullable()方法构造一个Optional对象,然后用map()计算学生的年龄,返回Optional对象(如果student为null, 返回map()方法返回一个空的Optinal对象)

map()

public static Optional<Integer> getAge(Student student)
{return Optional.ofNullable(student).map(u -> u.getAge()); 
}

map()+orElse()

Student student1 = new Student("aaa", 80);
Optional<Student> optional = Optional.ofNullable(student1);String stuName=optional.map(u -> u.getName()).map(name -> name.toUpperCase()).orElse(null);System.out.println(stuName);

filter()+map()

public boolean priceIsInRange1(Modem modem) {return Optional.ofNullable(modem2).map(Modem::getPrice).filter(p -> p >= 10).filter(p -> p <= 15).isPresent();
}

10、flatMap()解包

参考:Optional中map和flatMap的区别

  • flatMap使用场景:Optional嵌套成二维时使用(即使:Optional<Optional>),如果某对象实例的属性本身就为Optional包装过的类型,那么就要使用flatMap方法,就像School::getTearch返回的就是Optional类型的,所以不用再使用Optional进行包装;
  • map使用场景:对于返回值是其他类型,需要Optional进行包装,如Student::getName得到是String类型的,就需要使用map方法在其外面包装一层Optional对象。
    构建一个测试对象
public class School {private String name;private Optional<Tearch> 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> 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属性的值,可以使用下面的方式:
错的方式:

School::getTearch会返回School实例的tearch属性,而tearch属性是使用Optional包装的Tearch对象,所以使用了map(School::getTearch),会返回Optional<Optional>对象,而不是我们所想的Optional

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

正确的做饭:flatMap

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

11、stream()

功能:在 Java 9中添加到 Optional 类的最后一个方法是 stream() 方法,允许我们将 Optional 实例视为Stream

Optional<List<String>> value = Optional.of(Arrays.asList("aaaa","bbbb","ccc"));List<String> collect = value.stream().flatMap(Collection::stream).filter(v->v.length()==4).map(String::toUpperCase).collect(Collectors.toList());System.out.println(collect);//[AAAA, BBBB]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/217774.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一个最小的物联网系统设计方案及源码(一)——系统组成

关于物联网 物联网&#xff08;Internet of Things&#xff0c;缩写IOT&#xff09;是一个基于互联网、传统电信网等信息承载体&#xff0c;让所有能够被独立寻址的普通物理对象实现互联互通的网络。 物联网一般为无线网&#xff0c;由于每个人周围的设备可以达到一千至五千个&…

【unity】【WebRTC】从0开始创建一个Unity远程媒体流app-设置输入设备

【项目源码】 包括本篇需要的脚本都打包在项目源码中,可以通过下面链接下载: 【背景】 目前我们能投射到远端浏览器(或者任何其它Peer)的媒体流只有默认的MainCamera画面,其实我们还可以通过配置输入来传输操作输入信息,比如键鼠等。 【追加input processing组件】 …

React-hook-form-mui (一):基本使用

前言 在项目开发中&#xff0c;我们选择了ReactMUI作为技术栈。在使用MUI构建form表单时&#xff0c;我们发现并没有与antd类似的表单验证功能&#xff0c;于是我们选择了MUI推荐使用的react-hook-form-mui库去进行验证。但是发现网上关于这个库的使用方法和demo比较少且比较简…

【LinkedList】常用方法大全

1、添加元素&#xff1a; push、offerFirst都调用了addFirst函数&#xff0c;只不过push和addFirst一样没有返回值&#xff0c;offer会返回true&#xff1b;add背后通过linkLast(e)源码实现且有返回值 具体方法实现备注addpublic boolean add(E e) {linkLast(e); return true;}…

GEE:使用网格搜索法(Grid Search)求机器学习的最优参数或者参数组合

作者:CSDN @ _养乐多_ 本文记录了在 Google Earth Engine(GEE)平台中,计算机器学习分类算法最优参数的代码,其中包括单一参数的最优和不同参数组合的最优。使用的最优参数计算方法是网格搜索法(Grid Search),GEE 平台上并没有现成的网格搜索法 API,因此,本文在 GEE …

FPGA学习笔记-1 FPGA原理与开发流程

1 初识FPGA 文章目录 1 初识FPGA1.1 基本认知1.1.1 什么是FPGA&#xff1f;1.1.2 什么是HDL&#xff1f;什么是Verilog&#xff1f;1.1.3 硬件开发与软件开发1.1.4 FPGA与其他硬件的对比1.1.5 FPGA优势与局限性1.1.6 FPGA的应用1.1.7 FPGA的学习之路 1.2 FPGA开发流程1.2.1 一般…

安装Anaconda和pytorch

首先看下自己电脑是否有英伟达的显卡&#xff0c;如果有的话可以安装GPU版本&#xff0c;没有的话可以安装CPU版本。 CPU版本 1.安装Anaconda 首先去官网下载Anaconda。 点击download&#xff0c;下载的就是最新版本的。 下载完成后&#xff0c;直接运行下步就行 注意到路径…

python读取csv文件

在Python中&#xff0c;你可以使用pandas库来读取CSV文件。以下是一个基本的例子&#xff1a; import pandas as pd# 读取CSV文件data pd.read_csv(filename.csv)# 显示前几行数据print(data.head()) 这里&#xff0c;filename.csv应该被替换为你的CSV文件的实际路径和名称。…

SpringBoot 国际化-自定义 LocaleResolver

准备国际化文件 资源目录下创建 i18文件夹&#xff0c; i18 下面创建两个文件&#xff1a; 预配置信息 messages_en_US.preperties | successsuccess messages_zh_CN.properties | success操作成功在application.yml中指定国际化文件的位置 sp…

Web漏洞分析-文件解析及上传(上)

随着互联网的迅速发展&#xff0c;网络安全问题变得日益复杂&#xff0c;而文件解析及上传漏洞成为攻击者们频繁攻击的热点之一。本文将深入研究文件解析及上传漏洞&#xff0c;通过对文件上传、Web容器IIS、命令执行、Nginx文件解析漏洞以及公猫任意文件上传等方面的细致分析&…

「Verilog学习笔记」简易秒表

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点&#xff0c;刷题网站用的是牛客网 timescale 1ns/1nsmodule count_module(input clk,input rst_n,output reg [5:0]second,output reg [5:0]minute);always (posedge clk or negedge rst_n) begin if (~rst…

控制笔记本电脑性能,增强性能/控制发热---Thinkpad x280

1、引言 手上有一台收来办公的Thinkpad x280,但安装的联想管家却没有性能调节选项&#xff0c;导致电脑性能释放很不顺手。由于有室外办公需求&#xff0c;也就有续航需求&#xff0c;也是让它减少发热&#xff1b;同时我想在室内的时候&#xff0c;完整发挥它的性能&#xff…

Spring框架中的8种设计模式

前言 Spring框架中的8种设计模式分别是&#xff1a;1、简单工厂。2、工厂方法。3、单例模式。4、适配器模 式。5、装饰器模式。6、代理模式。7、观察者模式。8、策略模式. 1、简单工厂 Spring中的BeanFactory就是简单工厂模式的体现&#xff0c;根据传入一个唯一的标识来获…

<Halcon> 局部放大显示

局部放大显示 当读取的图片为超大分辨率时&#xff0c;我们需要对局部位置或定位到的位置在显示窗口放大显示&#xff0c;主要算子为dev_set_part。 read_image (Image, printer_chip/printer_chip_01) gen_rectangle1 (ROI_0, 617.275, 1347.28, 828.349, 1449.5) dev_set_p…

springcloud微服务篇--2.微服务之间的调用

一、微服务案例需求1&#xff1a; 根据订单id查询订单的同时&#xff0c;把订单所属的用户信息一起返回 1、新建订单项目&#xff0c;用户服务。 2.RestTemplate实现微服务之间的访问。 在order-service的OrderApplication中注册RestTemplate 注入调用&#xff1a; Autowire…

Android 12.0 Launcher3定制化之修改添加的默认文件夹为9宫格样式

1. 概述 在12.0的系统产品rom定制化开发中,对于Launcher3的定制功能也是不少的,比如在Launcher3中添加默认文件夹,把默认的app添加的文件夹里面,其他的app 然后按顺序排序。在文件夹布局就是默认的9宫格布局,接下来分析下相关源码来实现相关功能的实现 2.Launcher3定制化…

tcn 时间序列回归实例

目录 torch-tcn库 示例代码 自定义实现tcn层 torch-tcn库 pip install torch-tcn 示例代码 import torch from torch import nn from tcn import TCNLayerbatch_size = 16 seq_length = 100 # 序列长度 n_features = 32 # 特征数量 n_outputs = 10 # 输出大小# 输入…

C#基础——字符串、字符串API

C#基础——字符串、字符串API 字符串是 System.String 类的实例。字符串表示文本数据&#xff0c;可以包含字母、数字、符号和空格等字符。 创建字符串 string str1 "Hello, World!"; // 使用双引号创建字符串 string str2 "This is a C# string.";字符…

Pyhon基于YOLOV实现的车辆品牌及型号检测项目源码+模型+项目文档

项目运行运行录屏&#xff1a; Pyhon基于YOLOV实现的车辆品牌及型号检测项目运行录屏 完整代码下载地址&#xff1a;Pyhon基于YOLOV实现的车辆品牌及型号检测项目 项目背景&#xff1a; 车辆检测及型号识别广泛应用于物业&#xff0c;交通等的管理场景中。通过在停车场出入口…

【PTA刷题+代码+详解】求二叉树度为1的结点个数(递归法)

文章目录 题目C代码详解 题目 在二叉树T中&#xff0c;其度为1的结点是指某结点只有左孩子或只有右孩子。利用递归方法求二叉树T的度为1的结点个数。 1&#xff09;如果TNULL&#xff0c;则是空树&#xff0c;度为1的结点个数为0&#xff0c;返回值为0&#xff1b; 2&#xff0…