函数式编程-闭包、柯里化
闭包(Closure)
何为闭包,闭包就是函数对象与外界变量绑定在一起,形成的整体。例如
public class ClosureTest1 {
interface Lambda {
int add(int y);
}
public static void main(String[] args) {
int x = 10;
highOrder(y -> x + y);
}
static void highOrder(Lambda lambda) {
System.out.println(lambda.add(20));
}
}
- 代码中的 y \rightarrow x + y 和 x = 10,就形成了一个闭包
- 可以想象成,函数对象有个背包,背包里可以装变量随身携带,将来函数对象甭管传递到多远的地方,包里总装着个 x = 10
- 有个限制,局部变量 x 必须是 final 或 effective final 的,effective final 意思就是,虽然没有用 final 修饰,但就像是用 final 修饰了一样,不能重新赋值,否则就语法错误。
- 意味着闭包变量,在装进包里的那一刻,就不能变化了
- 道理也简单,为了保证函数的不变性,防止破坏成道
- 闭包是一种给函数执行提供数据的手段,函数执行既可以使用函数入参,还可以使用闭包变量
例
public class ClosureTest2 {
//创建10个任务对象,每个对象单独编号
@Test
void function() {
// 闭包作用:给函数对象提供参数以外的数据
List<Runnable> collect = IntStream.range(0, 10).mapToObj(i -> {
int no = i + 1;
return (Runnable) () -> System.out.println(Thread.currentThread().getName() + "-任务编号-" + no);
}).collect(Collectors.toList());
ExecutorService executorService = Executors.newSingleThreadExecutor();
collect.forEach(executorService::execute);
executorService.shutdown();
}
}
柯里化(Carrying)
柯里化的作用是让函数对象分步执行(本质上是利用多个函数对象和闭包)
例如:
public class Carrying1Test {
public static void main(String[] args) {
highOrder(a -> b -> a + b);
}
static void highOrder(Step1 step1) {
Step2 step2 = step1.exec(10);
System.out.println(step2.exec(20));
System.out.println(step2.exec(50));
}
interface Step1 {
Step2 exec(int a);
}
interface Step2 {
int exec(int b);
}
}
代码中
- a \rightarrow ... 是第一个函数对象,它的返回结果 b \rightarrow ... 是第二个函数对象
- 后者与前面的参数 a 构成了闭包
- step1.exec(10) 确定了 a 的值是 10
- ,返回第二个函数对象 step2,a 被放入了 step2 对象的背包记下来了
- step2.exec(20) 确定了 b 的值是 20,此时可以执行 a + b 的操作,得到结果 30
- step2.exec(50) 分析过程类似
例:
//把三份数据合在一起
interface Fa {
Fb apply(List<Integer> a);
}
interface Fb {
Fc apply(List<Integer> a);
}
interface Fc {
List<Integer> apply(List<Integer> a);
}
Fb step1() {
List<Integer> x = Arrays.asList(1, 2, 3);
return b -> c -> {
ArrayList<Integer> list = new ArrayList<>();
list.addAll(x);
list.addAll(b);
list.addAll(c);
return list;
};
}
Fc step2(Fb fb) {
List<Integer> y = Arrays.asList(4, 5, 6);
return fb.apply(y);
}
void step3(Fc fc) {
List<Integer> z = Arrays.asList(7, 8, 9);
List<Integer> apply = fc.apply(z);
System.out.println(apply);
}
@Test
void function1() {
step3(step2(step1()));
}
License:
CC BY 4.0