选取单个元素
直觉来说选取单个元素肯定会比选取多个要简单得多,不过这里也存在一些问题。我们先看下一般的做法的问题是什么,然后再看下如何用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
foundName.ifPresent(name -> System.out.println("Hello " + name));
跟命令式的选取第一个匹配名字的代码比起来,流式的优雅的函数式风格看真来更棒一些。不过这个调用流的版本里是不是做的事情有点太多了(译注:先选出了所有匹配的再返回第一项)?当然不是,这些方法非常智能,它们可以按需工作(在后面113页的Stream的惰性求值中我们会深入探讨这点)。
选取单个元素的例子展示了JDK库更多强大的功能,下面我们来看下lambda表达式如何根据一个集合,来求出一个想要的值。
问题内容: 如何在Java中模拟函数式编程,特别是如何将函数映射到项目集合? 什么是最冗长和尴尬的方法? 问题答案: 在Java之前,所有的函数式编程尝试在Java中都会有些 冗长 和/或 笨拙 ,直到Java 8。 最 直接的 方法是提供一个接口(例如Guava的这种形式),并提供采用和调用该接口的各种方法(例如我认为您的方法应该执行的操作)。 不好的事情是,您需要使用匿名内部类来实现并经常这样
本文向大家介绍详解JAVA 函数式编程,包括了详解JAVA 函数式编程的使用技巧和注意事项,需要的朋友参考一下 1.函数式接口 1.1概念: java中有且只有一个抽象方法的接口。 1.2格式: 1.3@FunctionalInterface注解: 与 @Override 注解的作用类似,Java 8中专门为函数式接口引入了一个新的注解: @FunctionalInterface 。该注 解可用于
本文向大家介绍Java函数式编程(七):MapReduce,包括了Java函数式编程(七):MapReduce的使用技巧和注意事项,需要的朋友参考一下 译注:map(映射)和reduce(归约,化简)是数学上两个很基础的概念,它们很早就出现在各类的函数编程语言里了,直到2003年Google将其发扬光大,运用到分布式系统中进行并行计算后,这个组合的名字才开始在计算机界大放异彩(那些函数式粉可能并不
本文向大家介绍Java函数式编程(九):Comparator,包括了Java函数式编程(九):Comparator的使用技巧和注意事项,需要的朋友参考一下 实现Comparator接口 Comparator接口的身影在JDK库中随处可见,从查找到排序,再到反转操作,等等。Java 8里它变成了一个函数式接口,这样的好处就是我们可以使用流式语法来实现比较器了。 我们用几种不同的方式来实现一下Comp
函数式编程 -> 函数响应式编程 现在大家已经了解我们是如何运用函数式编程来操作序列的。其实我们可以把这种操作序列的方式再升华一下。例如,你可以把一个按钮的点击事件看作是一个序列: // 假设用户在进入页面到离开页面期间,总共点击按钮 3 次 // 按钮点击序列 let taps: Array<Void> = [(), (), ()] // 每次点击后弹出提示框 taps.forEach {
函数式编程(functional programming)是一种编程范式(Programming paradigm),或者说编程模式,比如我们常见的过程式编程是一种编程范式,面向对象编程又是另一种编程范式。 函数式编程的一大特性就是:可以把函数当成变量来使用,比如将函数赋值给其他变量、把函数作为参数传递给其他函数、函数的返回值也可以是一个函数等等。 Python 不是纯函数式编程语言,但它对函数式