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
投稿

猜你喜欢

  • 利用Java Set 去除重复object的方法

    2023-07-27 09:41:57
  • Android仿微信雷达扫描效果的实现方法

    2022-07-28 01:49:17
  • Android实现截屏并保存操作功能

    2021-12-16 19:45:16
  • java实现文件的断点续传

    2023-11-23 09:11:00
  • android layout 按比例布局的代码

    2022-10-11 13:02:40
  • Android在类微信程序中实现蓝牙聊天功能的示例代码

    2023-09-07 06:36:19
  • java中javamail收发邮件实现方法

    2022-12-15 02:03:03
  • Maven项目修改JDK版本全过程

    2021-07-19 12:13:29
  • 详解spring cloud中使用Ribbon实现客户端的软负载均衡

    2022-10-26 15:54:45
  • C# 泛型接口的抗变和协变

    2022-05-07 09:34:31
  • C#异步编程Task的创建方式

    2023-07-23 06:22:43
  • Java 泛型总结(一):基本用法与类型擦除

    2023-06-11 20:33:10
  • Java 方法的重载与参数传递详解

    2023-10-19 18:50:46
  • 详解android是如何管理内存的

    2022-02-08 03:37:22
  • Java线程生命周期的终止与复位

    2022-04-22 01:57:01
  • Mybatis中的常用OGNL表达式

    2023-09-29 10:48:33
  • Java设计模式之中介者模式的实现方式

    2022-08-10 23:43:06
  • Java NIO中四大核心组件的使用详解

    2023-10-19 17:05:13
  • LINQ排序操作符用法

    2023-10-26 02:19:10
  • SpringBoot实现启动项目后立即执行的方法总结

    2022-07-31 15:01:16
  • asp之家 软件编程 m.aspxhome.com