Java 闭包复合,用户希望连续应用一系列简单且独立的函数,使用 Function
、Consumer
与 Predicate
接口中定义为默认方法的复合方法(composition method)。函数式编程的优点之一在于支持创建若干简单、可重复使用的函数,将这些函数组合在一起就能解决复杂的问题。
Java 闭包复合 问题描述
用户希望连续应用一系列简单且独立的函数。
Java 闭包复合 解决方案
使用 Function
、Consumer
与 Predicate
接口中定义为默认方法的复合方法(composition method)。
Java 闭包复合 具体实例
函数式编程的优点之一在于支持创建若干简单、可重复使用的函数,将这些函数组合在一起就能解决复杂的问题。为此,java.util.function
包引入的函数式接口定义了各种有助于简化复合操作的方法。
例如,Function
接口包括 compose
和 andThen
两种默认方法,二者的签名如例 5-23 所示。
例 5-23
Function
接口定义的复合方法
从方法签名中的哑元(dummy argument)不难看出两种方法的作用:compose
方法在原始函数之前应用其参数,而 andThen
方法在原始函数之后应用其参数。
为说明两种方法的应用,考虑例 5-24 所示的简单示例。
例 5-24
compose
和andThen
方法的应用
❶ 先执行 mult3
函数,再执行 add2
函数
❷ 先执行 add2
函数,再执行 mult3
函数
可以看到,add2
函数的作用是将参数加 2,而 mult3
函数的作用是将参数乘 3。通过 compose
方法创建的复合函数 mult3add2
先执行 mult3
,再执行 add2
;通过 andThen
方法创建的复合函数 add2mult3
则相反,先执行 add2
,再执行 mult3
。
两个复合函数的执行结果如下:
复合函数的结果仍然是函数,因此这个过程创建的操作可供今后使用。例如,如果收到的数据属于 HTTP 请求的一部分,说明数据是以字符串形式传输的。虽然已有可用于操作数据的方法,但前提为数据是数字。如果这种情况频繁发生,可以考虑在应用数值操作之前编写一个解析字符串数据的函数。详见例 5-25。
例 5-25 首先将字符串解析为整数,然后加 2
本例创建了一个名为 parseThenAdd2
的函数,它先调用静态方法 Integer.parseInt
,再将所得结果加 2。另一方面,也可以定义一个先执行数值操作,再调用 toString
方法的函数,如例 5-26 所示。
例 5-26 首先加 2,然后将数字转换为字符串
上述操作返回一个函数,它传入 Integer
参数并返回 String
。
如例 5-27 所示,Consumer
接口也定义了一个用于闭包复合的方法。
例 5-27
Consumer
接口定义的复合方法
根据 Javadoc 的描述,andThen
方法返回一个复合 Consumer
,它依次执行原始操作和 after
指定的操作。如果执行任一操作时抛出异常,异常将被转发给组合操作的调用者。
示例代码如例 5-28 所示。
例 5-28 用于打印和记录的复合
Consumer
程序首先创建了两个 Consumer
,一个用于打印结果到控制台,另一个用于日志记录。接下来,程序创建了一个复合 Consumer
,可以一次性打印并记录流的所有元素。
Predicate
接口定义了三种用于谓词复合的方法,如例 5-29 所示。
例 5-29
Predicate
接口定义的复合方法
and
、or
、negate
方法分别使用逻辑与、逻辑或、逻辑非操作实现谓词的复合,每种方法返回一个复合 Predicate
。
接下来,我们讨论一个关于整数的有趣问题。完全平方数(perfect square)是其平方根同样为整数的数,而三角形数(triangle number)是一定数目的点或圆在等距离排列下可以形成等边三角形的数8。
8参见维基百科有关“三角形数”的介绍。在一个房间中,如果每个人只与其他人握手一次,则三角形数是握手次数的总和。(例如,房间中有 2 个人时握手次数为 1,有 3 个人时握手次数为 3,有 4 个人时握手次数为 6,有 5 个人时握手次数为 10,有 6 个人时握手次数为 15,以此类推。那么 1、3、6、10、15 就是前 5 个三角形数,第 n 个三角形数的计算公式为
例 5-30 创建了两个用于计算完全平方数和三角形数的方法,并通过 and
方法查找既是完全平方数,又是三角形数的数。
例 5-30 既是完全平方数,又是三角形数的数
❶ 部分完全平方数:1、4、9、16、25、36、49、64、81……
❷ 部分三角形数:1、3、6、10、15、21、28、36、45……
❸ 既是完全平方数,又是三角形数(1 到 10 000 之间):1、36、1225
借由复合函数,可以将若干简单的函数组合在一起以构建复杂的操作 9。
9Unix 操作系统就是基于这种理念构建的,具有类似的优点。