Java函数式编程(六):Optional

作者:junjie 时间:2021-07-04 21:44:05 

选取单个元素

直觉来说选取单个元素肯定会比选取多个要简单得多,不过这里也存在一些问题。我们先看下一般的做法的问题是什么,然后再看下如何用lambda表达式来解决它。

我们先新建一个方法来查找一个以特定字母开头的元素,然后打印出来。


public static void pickName(
final List<String> names, final String startingLetter) {
String foundName = null;
for(String name : names) {
if(name.startsWith(startingLetter)) {
foundName = name;
break;
}
}

这个方法简直跟刚过去的垃圾车一样臭不可闻。我们先是新建了一个foundName的变量,然后初始化成null——这个就是恶臭之源。我们不得不检查是否为空,不然的话就会抛出一个NullPointerException或者一个错误响应。我们还用了一个外部迭代器来循环列表,如果找到了想要的元素之后还得跳出这个循环,这又加重了原来的臭味:基本类型偏执,命令式风格,可变性,全齐活了。一旦退出循环后,我们还得先检查下结果,然后才能进行打印。这么点任务居然写了这么长的代码。

我们来重新分析下这个问题。我们只是希望能选出第一个匹配的元素,并且能安全的处理不存在这样一个元素的情况。我们来用lambda表达式重写一下这个pickName方法。


public static void pickName(
final List<String> names, final String startingLetter) {
final Optional<String> foundName =
names.stream()
.filter(name ->name.startsWith(startingLetter))
.findFirst();
System.out.println(String.format("A name starting with %s: %s",
startingLetter, foundName.orElse("No name found")));
}

JDK里面一些强大的功能使得这段代码更得非常简洁。首先我们用filter方法获取了所有满足条件的元素,然后用了Stream类的findFirst方法选取出了返回集合的第一个元素。这个方法返回的是一个Optional对象,这就是Java里面官方认证的null变量的除臭剂。

Optional类非常有用,你不用管结果是不是存在。它使得我们免受空指针异常的烦恼,并且更明确的指明了没有结果也是一种可能的结果。通过isPresent()方法我们可以知道结果是不是存在,想获取结果值的话可以使用get()方法。我们还可以使用(这个方法名能让你震惊)orElse方法给它设置一个默认值,就像前面代码里的那样。

我们用之前一直在用的friends集合来验证下我们这个pickName方法。


pickName(friends, "N");
pickName(friends, "Z");


这段代码选取出第一个匹配的元素,如果没找到,打印出一个友好的提示信息。


A name starting with N: Nate
A name starting with Z: No name found


findFirst()方法和Optinal类的结合使用减少了我们的代码量,并且看起来感觉还不错。不过Optional类的功能远不止这些。比如说,除了当对象不存在的时候能提供一个默认值外,如果结果存在的话还可以用它来运行一段代码,或者一个lambda表达式,像这样:


foundName.ifPresent(name -> System.out.println("Hello " + name));

跟命令式的选取第一个匹配名字的代码比起来,流式的优雅的函数式风格看真来更棒一些。不过这个调用流的版本里是不是做的事情有点太多了(译注:先选出了所有匹配的再返回第一项)?当然不是,这些方法非常智能,它们可以按需工作(在后面113页的Stream的惰性求值中我们会深入探讨这点)。

选取单个元素的例子展示了JDK库更多强大的功能,下面我们来看下lambda表达式如何根据一个集合,来求出一个想要的值。

标签:Java,函数式编程,Optional
0
投稿

猜你喜欢

  • IntelliJ IDEAx导出安卓(Android)apk文件图文教程

    2022-06-22 18:26:16
  • SpringBoot2学习之springboot与spring区别分析

    2023-02-22 17:44:28
  • java获取和设置系统变量问题(环境变量)

    2023-11-19 07:34:07
  • SpringBoot打成war包在tomcat或wildfly下运行的方法

    2023-11-23 08:20:56
  • java分页工具类的使用方法

    2023-08-17 02:00:14
  • c#和avascript加解密之间的互转代码分享

    2022-03-22 10:15:28
  • Java中Range函数的简单介绍

    2023-10-18 05:33:35
  • java使用Jsoup组件生成word文档

    2022-10-28 12:44:16
  • Spring中自动注入的两种方式总结

    2022-10-24 08:54:14
  • Java全面细致讲解类与对象

    2022-07-07 07:04:42
  • Spring学习笔记之bean的基础知识

    2021-09-08 10:09:27
  • 新手小白学JAVA IDEA下载使用手册全集

    2023-11-23 14:33:23
  • java Springboot实现多文件上传功能

    2023-11-09 04:31:32
  • C#实现截图工具小项目

    2023-10-02 08:20:03
  • Android使用Gradle依赖配置compile、implementation与api的区别介绍

    2023-09-27 18:11:40
  • Java面向对象基础知识之封装,继承,多态和抽象

    2022-11-18 07:35:59
  • 使用Springboot对配置文件中的敏感信息加密

    2021-05-24 10:50:25
  • Java实现堆排序和图解

    2023-11-11 12:13:37
  • SpringBoot项目多数据源及mybatis 驼峰失效的问题解决方法

    2023-07-25 07:09:08
  • C#复制数组的两种方式及效率比较

    2023-07-15 04:19:12
  • asp之家 软件编程 m.aspxhome.com