Java 8 Optional类深度解析

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

身为一名Java程序员,大家可能都有这样的经历:调用一个方法得到了返回值却不能直接将返回值作为参数去调用别的方法。我们首先要判断这个返回值是否为null,只有在非空的前提下才能将其作为其他方法的参数。这正是一些类似Guava的外部API试图解决的问题。一些JVM编程语言比如Scala、Ceylon等已经将对在核心API中解决了这个问题。在我的前一篇文章中,介绍了Scala是如何解决了这个问题。

新版本的Java,比如Java 8引入了一个新的Optional类。Optional类的Javadoc描述如下:

这是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。

本文会逐个探讨Optional类包含的方法,并通过一两个示例展示如何使用。

1、of

为非null的值创建一个Optional。

of方法通过工厂方法创建Optional类。需要注意的是,创建对象时传入的参数不能为null。如果传入参数为null,则抛出NullPointerException 。

//调用工厂方法创建Optional实例
Optional<String> name = Optional.of("Sanaulla");
//传入参数为null,抛出NullPointerException.
Optional<String> someNull = Optional.of(null);

2、ofNullable

为指定的值创建一个Optional,如果指定的值为null,则返回一个空的Optional。

ofNullable与of方法相似,唯一的区别是可以接受参数为null的情况。示例如下:

//下面创建了一个不包含任何值的Optional实例
//例如,值为'null'
Optional empty = Optional.ofNullable(null);

3、isPresent

非常容易理解

如果值存在返回true,否则返回false。

类似下面的代码:

//isPresent方法用来检查Optional实例中是否包含值
if (name.isPresent()) {//在Optional实例内调用get()返回已存在的值System.out.println(name.get());//输出Sanaulla
}

4、get

如果Optional有值则将其返回,否则抛出NoSuchElementException。

上面的示例中,get方法用来得到Optional实例中的值。下面我们看一个抛出NoSuchElementException的例子:

//执行下面的代码会输出:No value present 
try {//在空的Optional实例上调用get(),抛出NoSuchElementExceptionSystem.out.println(empty.get());
} catch (NoSuchElementException ex) {System.out.println(ex.getMessage());
}

5、ifPresent

如果Optional实例有值则为其调用consumer,否则不做处理

要理解ifPresent方法,首先需要了解Consumer类。简答地说,Consumer类包含一个抽象方法。该抽象方法对传入的值进行处理,但没有返回值。Java8支持不用接口直接通过lambda表达式传入参数。

如果Optional实例有值,调用ifPresent()可以接受接口段或lambda表达式。类似下面的代码:

//ifPresent方法接受lambda表达式作为参数。
//lambda表达式对Optional的值调用consumer进行处理。
name.ifPresent((value) -> {System.out.println("The length of the value is: " + value.length());
});

6、orElse

如果有值则将其返回,否则返回指定的其它值。

如果Optional实例有值则将其返回,否则返回orElse方法传入的参数。示例如下:

//如果值不为null,orElse方法返回Optional实例的值。
//如果为null,返回传入的消息。
//输出:There is no value present!
System.out.println(empty.orElse("There is no value present!"));
//输出:Sanaulla
System.out.println(name.orElse("There is some value!"));

7、orElseGet

orElseGet与orElse方法类似,区别在于得到的默认值。orElse方法将传入的字符串作为默认值,orElseGet方法可以接受Supplier接口的实现用来生成默认值。示例如下:

//orElseGet与orElse方法类似,区别在于orElse传入的是默认值,
//orElseGet可以接受一个lambda表达式生成默认值。
//输出:Default Value
System.out.println(empty.orElseGet(() -> "Default Value"));
//输出:Sanaulla
System.out.println(name.orElseGet(() -> "Default Value"));

8、orElseThrow

如果有值则将其返回,否则抛出supplier接口创建的异常。

在orElseGet方法中,我们传入一个Supplier接口。然而,在orElseThrow中我们可以传入一个lambda表达式或方法,如果值不存在来抛出异常。示例如下:

try {//orElseThrow与orElse方法类似。与返回默认值不同,//orElseThrow会抛出lambda表达式或方法生成的异常 empty.orElseThrow(ValueAbsentException::new);
} catch (Throwable ex) {//输出: No value present in the Optional instanceSystem.out.println(ex.getMessage());
}

ValueAbsentException定义如下:

class ValueAbsentException extends Throwable {public ValueAbsentException() {super();}public ValueAbsentException(String msg) {super(msg);}@Overridepublic String getMessage() {return "No value present in the Optional instance";}
}

9、map

map方法文档说明如下:

如果有值,则对其执行调用mapping函数得到返回值。如果返回值不为null,则创建包含mapping返回值的Optional作为map方法返回值,否则返回空Optional。

map方法用来对Optional实例的值执行一系列操作。通过一组实现了Function接口的lambda表达式传入操作。如果你不熟悉Function接口,可以参考我的这篇博客。map方法示例如下:

//map方法执行传入的lambda表达式参数对Optional实例的值进行修改。
//为lambda表达式的返回值创建新的Optional实例作为map方法的返回值。
Optional<String> upperName = name.map((value) -> value.toUpperCase());
System.out.println(upperName.orElse("No value found"));

10、flatMap

如果有值,为其执行mapping函数返回Optional类型返回值,否则返回空Optional。flatMap与map(Funtion)方法类似,区别在于flatMap中的mapper返回值必须是Optional。调用结束时,flatMap不会对结果用Optional封装。

flatMap方法与map方法类似,区别在于mapping函数的返回值不同。map方法的mapping函数返回值可以是任何类型T,而flatMap方法的mapping函数必须是Optional。

参照map函数,使用flatMap重写的示例如下:

//flatMap与map(Function)非常类似,区别在于传入方法的lambda表达式的返回类型。
//map方法中的lambda表达式返回值可以是任意类型,在map函数返回之前会包装为Optional。 
//但flatMap方法中的lambda表达式返回值必须是Optionl实例。 
upperName = name.flatMap((value) -> Optional.of(value.toUpperCase()));
System.out.println(upperName.orElse("No value found"));//输出SANAULLA

11、filter

filter个方法通过传入限定条件对Optional实例的值进行过滤。文档描述如下:

如果有值并且满足断言条件返回包含该值的Optional,否则返回空Optional。

读到这里,可能你已经知道如何为filter方法传入一段代码。是的,这里可以传入一个lambda表达式。对于filter函数我们应该传入实现了Predicate接口的lambda表达式。如果你不熟悉Predicate接口,可以参考这篇文章。

现在我来看看filter的各种用法,下面的示例介绍了满足限定条件和不满足两种情况:

//filter方法检查给定的Option值是否满足某些条件。
//如果满足则返回同一个Option实例,否则返回空Optional。
Optional<String> longName = name.filter((value) -> value.length() > 6);
System.out.println(longName.orElse("The name is less than 6 characters"));//输出Sanaulla//另一个例子是Optional值不满足filter指定的条件。
Optional<String> anotherName = Optional.of("Sana");
Optional<String> shortName = anotherName.filter((value) -> value.length() > 6);
//输出:name长度不足6字符
System.out.println(shortName.orElse("The name is less than 6 characters"));

以上,我们介绍了Optional类的各个方法。下面通过一个完整的示例对用法集中展示:

public class OptionalDemo {public static void main(String[] args) {//创建Optional实例,也可以通过方法返回值得到。Optional<String> name = Optional.of("Sanaulla");//创建没有值的Optional实例,例如值为'null'Optional empty = Optional.ofNullable(null);//isPresent方法用来检查Optional实例是否有值。if (name.isPresent()) {//调用get()返回Optional值。System.out.println(name.get());}try {//在Optional实例上调用get()抛出NoSuchElementException。System.out.println(empty.get());} catch (NoSuchElementException ex) {System.out.println(ex.getMessage());}//ifPresent方法接受lambda表达式参数。//如果Optional值不为空,lambda表达式会处理并在其上执行操作。name.ifPresent((value) -> {System.out.println("The length of the value is: " + value.length());});//如果有值orElse方法会返回Optional实例,否则返回传入的错误信息。System.out.println(empty.orElse("There is no value present!"));System.out.println(name.orElse("There is some value!"));//orElseGet与orElse类似,区别在于传入的默认值。//orElseGet接受lambda表达式生成默认值。System.out.println(empty.orElseGet(() -> "Default Value"));System.out.println(name.orElseGet(() -> "Default Value"));try {//orElseThrow与orElse方法类似,区别在于返回值。//orElseThrow抛出由传入的lambda表达式/方法生成异常。empty.orElseThrow(ValueAbsentException::new);} catch (Throwable ex) {System.out.println(ex.getMessage());}//map方法通过传入的lambda表达式修改Optonal实例默认值。 //lambda表达式返回值会包装为Optional实例。Optional<String> upperName = name.map((value) -> value.toUpperCase());System.out.println(upperName.orElse("No value found"));//flatMap与map(Funtion)非常相似,区别在于lambda表达式的返回值。//map方法的lambda表达式返回值可以是任何类型,但是返回值会包装成Optional实例。//但是flatMap方法的lambda返回值总是Optional类型。upperName = name.flatMap((value) -> Optional.of(value.toUpperCase()));System.out.println(upperName.orElse("No value found"));//filter方法检查Optiona值是否满足给定条件。//如果满足返回Optional实例值,否则返回空Optional。Optional<String> longName = name.filter((value) -> value.length() > 6);System.out.println(longName.orElse("The name is less than 6 characters"));//另一个示例,Optional值不满足给定条件。Optional<String> anotherName = Optional.of("Sana");Optional<String> shortName = anotherName.filter((value) -> value.length() > 6);System.out.println(shortName.orElse("The name is less than 6 characters"));}}

上述代码输出如下:

Sanaulla
No value present
The length of the value is: 8
There is no value present!
Sanaulla
Default Value
Sanaulla
No value present in the Optional instance
SANAULLA
SANAULLA
Sanaulla
The name is less than 6 characters

转载于:https://my.oschina.net/u/3136594/blog/1585708

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

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

相关文章

鸽子 迷信_人工智能如何帮助我战胜鸽子

鸽子 迷信鸽子回避系统 (Pigeon Avoidance System) Disclaimer: You are reading Part 1 that gives an overview of the project. Part 2 describes the technical setup and data collection. Part 3 is about how to train the Pigeon Recognition Model and run it on Rasp…

华为鸿蒙会议安排,2020华为HDC日程确定,鸿蒙、HMS以及EMUI 11成最关注点

原标题&#xff1a;2020华为HDC日程确定&#xff0c;鸿蒙、HMS以及EMUI 11成最关注点HDC&#xff1a;华为开发者大会&#xff0c;目前已经确定将在9月10日正式开幕。日前华为已经在其官网公布了HDC的日程&#xff0c;从现在的消息看华为开发者大会有三大点最受业内关注。鸿蒙操…

反射、元类

一、反射 1、什么是反射&#xff1a;就是反省&#xff0c;自省的意思 反射指的是一个对象应该具备&#xff0c;可以增、删、改、查属性的能力&#xff0c;通过字符串来操作属性 涉及的四个函数&#xff0c;这四个函数就是普通的内置函数&#xff0c;只是没有下划线而已&#xf…

html收款页面模板,订单收款.html

&#xfeff;订单收款$axure.utils.getTransparentGifPath function() { return resources/images/transparent.gif; };$axure.utils.getOtherPath function() { return resources/Other.html; };$axure.utils.getReloadPath function() { return resources/reload.html; };…

pandas之时间数据

1.时间戳Timestamp() 参数可以为各种形式的时间&#xff0c;Timestamp()会将其转换为时间。 time1 pd.Timestamp(2019/7/13) time2 pd.Timestamp(13/7/2019 13:05) time3 - pd.Timestamp(2019-7-13) time4 pd.Timestamp(2019 7 13 13:05) time5 pd.Timestamp(2019 July 13 …

scikit keras_Scikit学习,TensorFlow,PyTorch,Keras…但是天秤座呢?

scikit kerasWelcome all! In the first episode of this series, I investigated the four most known machine learning frameworks and discussed which of these you should learn depending on your needs and goals.w ^迎阅读所有&#xff01; 在本系列的第一集中 &#…

Educational Codeforces Round 25 C. Multi-judge Solving

题目链接&#xff1a;http://codeforces.com/contest/825/problem/C C. Multi-judge Solving time limit per test1 secondmemory limit per test256 megabytesinputstandard inputoutputstandard outputMakes solves problems on Decoforces and lots of other different onli…

山东省2021年高考成绩查询平台6,山东2021年高考成绩改为6月26日前公布

6月11日&#xff0c;山东省教育厅举行2021年第一次高考新闻发布会&#xff0c;介绍2021年高考基本情况、评卷安排、成绩公布等相关工作。山东省教育招生考试院新闻发言人、普招处处长李春光介绍&#xff0c;根据近期国家有关工作要求和强基计划招生工作需要&#xff0c;原定于6…

如何在vuejs里禁用eslint语法检查工具

eslint好是好&#xff0c;可要求很苛刻&#xff0c;对于我这种写代码很糙的媛。。。。。。 搜索的时候有的说加入 /* eslint-disabled */&#xff08;有用&#xff0c;但只是部分代码享受此待遇&#xff09; 还有说删除.eslintrc.js里包含eslint关键字的块&#xff0c;a---o---…

数据结构两个月学完_这是我作为数据科学家两年来所学到的

数据结构两个月学完It has been 2 years ever since I started my data science journey. Boy, that was one heck of a roller coaster ride!自从我开始数据科学之旅以来已经有两年了 。 男孩 &#xff0c;那可真是坐过山车&#xff01; There were many highs and lows, and…

数学哲学与科学哲学和计算机科学的能动作用,数学哲学与科学哲学和计算机科学的能动作用...

3 数学哲学与计算机科学的能动作用数学哲学对于计算机科学的影响主要表现于以下的事实&#xff1a;一些源于数学哲学(数学基础研究)的概念和理论在计算机科学的历史发展中发挥了十分重要的作用。例如&#xff0c;在此可以首先提及(一阶)谓词演算理论&#xff1a;这是由弗雷格(…

AngularDart4.0 指南- 表单

2019独角兽企业重金招聘Python工程师标准>>> 表单是商业应用程序的主流。您可以使用表单登录&#xff0c;提交帮助请求&#xff0c;下订单&#xff0c;预订航班&#xff0c;安排会议&#xff0c;并执行无数其他数据录入任务。 在开发表单时&#xff0c;创建一个数据…

迈向数据科学的第一步:在Python中支持向量回归

什么是支持向量回归&#xff1f; (What is Support Vector Regression?) Support vector regression is a special kind of regression that gives you some sort of buffer or flexibility with the error. How does it do that ? I’m going to explain it to you in simpl…

jQuery事件整合

一、jQuery事件 1、focus&#xff08;&#xff09;元素获得焦点 2、blur&#xff08;&#xff09;元素失去焦点 3、change&#xff08;&#xff09; 表单元素的值发生变化&#xff08;可用于验证用户名是否存在&#xff09; 4、click&#xff08;&#xff09; 鼠标单击 5、dbc…

tableau跨库创建并集_刮擦柏林青年旅舍,并以此建立一个Tableau全景。

tableau跨库创建并集One of the coolest things about making our personal project is the fact that we can explore topics of our own interest. On my case, I’ve had the chance to backpack around the world for more than a year between 2016–2017, and it was one…

1.0 Hadoop的介绍、搭建、环境

HADOOP背景介绍 1.1 Hadoop产生背景 HADOOP最早起源于Nutch。Nutch的设计目标是构建一个大型的全网搜索引擎&#xff0c;包括网页抓取、索引、查询等功能&#xff0c;但随着抓取网页数量的增加&#xff0c;遇到了严重的可扩展性问题——如何解决数十亿网页的存储和索引问题。20…

如何实现多维智能监控?--AI运维的实践探索【一】

作者丨吴树生&#xff1a;腾讯高级工程师&#xff0c;负责SNG大数据监控平台建设。近十年监控系统开发经验&#xff0c;具有构建基于大数据平台的海量高可用分布式监控系统研发经验。 导语&#xff1a;监控数据多维化后&#xff0c;带来新的应用场景。SNG的哈勃多维监控平台在完…

使用Python和MetaTrader在5分钟内开始构建您的交易策略

In one of my last posts, I showed how to create graphics using the Plotly library. To do this, we import data from MetaTrader in a ‘raw’ way without automation. Today, we will learn how to automate this process and plot a heatmap graph of the correlation…

请对比html与css的异同,css2与css3的区别是什么?

css主要有三个版本&#xff0c;分别是css1、css2、css3。css2使用的比较多&#xff0c;因为css1的属性比较少&#xff0c;而css3有一些老式浏览器并不支持&#xff0c;所以大家在开发的时候主要还是使用css2。CSS1提供有关字体、颜色、位置和文本属性的基本信息&#xff0c;该版…

ipywidgets_未来价值和Ipywidgets

ipywidgetsHow to use Ipywidgets to visualize future value with different interest rates.如何使用Ipywidgets可视化不同利率下的未来价值。 There are some calculations that even being easy becoming better with a visualization of his terms. Moreover, the sooner…