引用的 IntBinaryOperator 接口类型是为函数接受两个整型参数,并返回一个整型值:
IntBinaryOperator mult2 = (n1, n2) -> n1 * n2;mult2.applyAsInt(10, 20); // 200mult2.applyAsInt(10, 30); // 300
引用 mult2 强调了需要两个显式参数,在本例中是 10 和 20 。
前面介绍的 IntUnaryOperator 比 IntBinaryOperator 简单,因为前者只需要一个参数,而后者则需要两个参数 。两者均返回整数值 。因此,目标是将名为 mult2 的两个参数 IntBinraryOperator 柯里化成一个单一的 IntUnaryOperator 版本 curriedMult2 。
考虑 IntFunction<R> 类型 。此类型的函数采用整型参数,并返回类型为 R 的结果,该结果可以是另一个函数 —— 更准确地说,是 IntBinaryOperator 。让一个 lambda 返回另一个 lambda 很简单:
arg1 -> (arg2 -> arg1 * arg2) // 括号可以省略
完整的 lambda 以 arg1 开头,而该 lambda 的主体以及返回的值是另一个以 arg2 开头的 lambda 。返回的 lambda 仅接受一个参数(arg2),但返回了两个数字的乘积(arg1 和 arg2) 。下面的概述,再加上代码,应该可以更好地进行说明 。
以下是如何柯里化 mult2 的概述:
- 类型为 IntFunction<IntUnaryOperator> 的 lambda 被写入并调用,其整型值为 10 。返回的 IntUnaryOperator 缓存了值 10,因此变成了已柯里化版本的 mult2,在本例中为 curriedMult2 。
- 然后使用单个显式参数(例如,20)调用 curriedMult2 函数,该参数与缓存的参数(在本例中为 10)相乘以生成返回的乘积 。。
// 创建一个接受一个参数 n1 并返回一个单参数 n2 -> n1 * n2 的函数,该函数返回一个(n1 * n2 乘积的)整型数 。IntFunction<IntUnaryOperator> curriedMult2Maker = n1 -> (n2 -> n1 * n2);
调用 curriedMult2Maker 生成所需的 IntUnaryOperator 函数:// 使用 curriedMult2Maker 获取已柯里化版本的 mult2 。// 参数 10 是上面的 lambda 的 n1 。IntUnaryOperator curriedMult2 = curriedMult2Maker2.apply(10);
值 10 现在缓存在 curriedMult2 函数中,以便 curriedMult2 调用中的显式整型参数乘以 10:curriedMult2.applyAsInt(20); // 200 = 10 * 20curriedMult2.applyAsInt(80); // 800 = 10 * 80
缓存的值可以随意更改:curriedMult2 = curriedMult2Maker.apply(50); // 缓存 50curriedMult2.applyAsInt(101); // 5050 = 101 * 50
当然,可以通过这种方式创建多个已柯里化版本的 mult2,每个版本都有一个 IntUnaryOperator 。柯里化充分利用了 lambda 的强大功能:可以很容易地编写 lambda 表达式来返回需要的任何类型的值,包括另一个 lambda 。
总结Java 仍然是基于类的面向对象的编程语言 。但是,借助流 API 及其支持的函数式构造,Java 向函数式语言(例如 Lisp)迈出了决定性的(同时也是受欢迎的)一步 。结果是 Java 更适合处理现代编程中常见的海量数据流 。在函数式方向上的这一步还使以在前面的代码示例中突出显示的管道的方式编写清晰简洁的 Java 代码更加容易:
dataStream .parallelStream() // 多线程以提高效率 .filter(...) // 阶段 1 .map(...) // 阶段 2 .filter(...) // 阶段 3 ... .collect(...); // 或者,也可以进行归约:阶段 N
自动多线程,以 parallel 和 parallelStream 调用为例,建立在 Java 的 fork/join 框架上,该框架支持 任务窃取(task stealing) 以提高效率 。假设 parallelStream 调用后面的线程池由八个线程组成,并且 dataStream 被八种方式分区 。某个线程(例如,T1)可能比另一个线程(例如,T7)工作更快,这意味着应该将 T7 的某些任务移到 T1 的工作队列中 。这会在运行时自动发生 。
推荐阅读
- c语言退出程序命令exit c语言exit函数用法
- 矩阵所有元素求和的公式 matlab矩阵求和函数
- c语言圆的面积编程 c语言阶乘函数怎么写
- 同位语从句经典例句 求同位语的具体用法和例句分析。
- spend的用法
- 并列连词 并列连词与从属连词的用法区别?
- 《如龙:极》鬼炎用法技巧解析攻略
- 对马岛之魂辅助功能有什么 对马之魂辅助功能用法介绍
- 团战经理骑士怎么用 团战经理骑士用法详解
- 团战经理狙击手好用吗 团战经理狙击手用法介绍