0%

lambda表达式


什么是lambda表达式

“Lambda 表达式”(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。Lambda表达式可以表示闭包(注意和数学传统意义上的不同)。

下面是我们常见的命令式编程
1
2
3
4
5
6
7
8
9
10
public class LambdaDemo {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("start");
}
}).start();
}
}
下面这个就是函数式编程
1
2
3
4
5
public class LambdaDemo {
public static void main(String[] args) {
new Thread(() -> System.out.println("start")).start();
}
}

由此可见我们可以对一些接口代码进行简化,但是是什么样的接口都可以使用lambda表达式吗?显然不是的。接口必须满足接口里面只有一个要实现的方法。我们可以在想要实现函数式编程的接口添加注解@FunctionalInterface,进行编译期间的校验,当接口不满足我们的条件的时候,将会有错误信息。


默认方法

在上面我们说了接口要实现只有一个要实现的方法,并不是说接口只能有一个方法,这个时候我们可以使用比如像默认方法这样的方式来解决

1
2
3
4
5
6
7
@FunctionalInterface
interface InterfaceTest{
int add(int i, int j);
default void print() {
System.out.println("This is default method");
}
}


函数式编程

这里写图片描述


静态方法 动态方法的引用

下面是对于一些常见方法引用的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
public class MethodReferenceDemo {
public static void main(String[] args) {
// 方法引用
Consumer<String> consumer1 = System.out::println;
consumer1.accept("接受的");

// 静态方法的引用
Consumer<Dog> consumer2 = Dog::bark;
Dog dog = new Dog();
consumer2.accept(dog);

// 非静态方法引用,使用对象实例的方法引用
// Function<Integer, Integer> function = dog::eat;
// UnaryOperator<Integer> function = dog::eat;
// System.out.println("还剩下" + function.apply(2) + "斤");

IntUnaryOperator function = dog::eat;
System.out.println("还剩下" + function.applyAsInt(2) + "斤");

//用类名来引用非静态方法
BiFunction<Dog, Integer, Integer> eatFunction = Dog::eat;
System.out.println("还剩下" + eatFunction.apply(dog, 2) + "斤");

// 构造函数的方法引用
Supplier<Dog> dogSupplier = Dog::new;
System.out.println("创建了新对象:" + dogSupplier.get());

// 带参数的构造方法的引用
Function<String, Dog> dogFunction = Dog::new;
System.out.println("创建了新对象:" + dogFunction.apply("旺财"));
}

}

class Dog{
private String name = "dog";

private Integer food = 10;

public Dog(){}

public Dog(String name){
this.name = name;
}
public static void bark(Dog dog){
System.out.println(dog + "叫了");
}

public int eat(int i){
System.out.println("吃了" + i + "斤");
this.food -= i;
return this.food;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
'}';
}
}


级联和柯

  • 柯里化:把多个参数的函数转换成只有一个参数的函数
  • 柯里化的目的:函数标准化
  • 高阶函数:返回函数的函数

下面是对级联和柯里化的一些代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class CurryDemo {

public static void main(String[] args) {

// 级联表达式
Function<Integer, Function<Integer, Integer>> fun1 = x -> y -> x + y;
System.out.println(fun1.apply(1).apply(2));

Function<Integer, Function<Integer, Function<Integer, Integer>>> fun2 = x -> y -> z -> x + y + z;
System.out.println(fun2.apply(1).apply(2).apply(3));

int[] nums = {2, 3, 4};
Function f = fun2;
for(int i : nums){
if(f instanceof Function){
Object obj = f.apply(i);
if(obj instanceof Function){
f = (Function) obj;
}else {
System.out.println("调用结束:结果为" + obj);
}
}
}
}
}