前言
Java8的 Lambda表达式 ,通过lambda表达式可以替代我们之前写的匿名内部类来实现接口。lambda表达式本质是一个匿名函数。
1、lambda表达式本质是一个匿名函数。
1 package com.demo.main;
2
3 public class LambdaMain {
4
5 public static void main(String[] args) {
6
7 // 1、创建一个匿名内部类
8 Addition addition = new Addition() {
9
10 @Override
11 public int add(int a, int b) {
12
13 return a + b;
14 }
15
16 };
17 // 传统的匿名内部类来实现接口。
18 System.out.println("调用匿名内部类来实现接口:" + addition.add(2, 3));
19
20 // 2、Java8的lambda表达式,通过lambda表达式可以替代我们之前写的匿名内部类来实现接口。
21 // lambda表达式本质是一个匿名函数。
22 // 2.1、lambda由三部分组成,()是参数列表,->剪头符号,{}代表方法体。
23 Addition a2 = (int a, int b) -> {
24 return a + b;
25 };
26 System.out.println("lambda表达式a2:" + a2.add(3, 3));
27
28 // 2.2、可以省略参数列表里面的参数类型
29 Addition a3 = (a, b) -> {
30 return a + b;
31 };
32 System.out.println("lambda表达式a3:" + a3.add(3, 3));
33
34 }
35
36 /**
37 *
38 * @author 创建一个接口,定义一个方法
39 *
40 */41 interface Addition {
42
43 /**
44 * 加法的方法
45 *
46 * @param a
47 * @param b
48 * @return
49 */50 int add(int a, int b);
51 }
52
53 }
2、Lambda表达式语法
形如(int a, int b) -> {return a + b;},lambda本质就是一个(匿名)函数,匿名函数,就是没有方法名称的函数。
1 一般函数结构类似,如下所示:
2 int add(int a, int b){
3 return a + b;
4 }
5
6 一般函数的,结构如:返回值 方法名称(参数列表) 方法体。
3、而Lamdba表达式函数
只有参数列表和方法体。结构如:(参数列表) -> {方法体};
详细说明,如下所示:
1)、()括号用来描述参数列表。
2)、{} 大括号 用来描述方法体。
3)、->尖括号,Lambda运算符,可以叫做箭头符号,或者goes to。
4、Lambda表达式语法
关于接口方法参数、无参、单个参数、两个参数、有返回值、没有返回值的情况。如何来根据lambda来返回接口函数。
1 package com.demo.main;
2
3 public class LambdaMain {
4
5 public static void main(String[] args) {
6 // 1、无参数无返回值
7 MethodNoReturnNoParam methodNoReturnNoParam = () -> {
8 System.out.println("无参数无返回值");
9 };
10 methodNoReturnNoParam.lambda1();
11
12 // 2、单个参数无返回值
13 MethodNoReturnOneParam methodNoReturnOneParam = (int a) -> {
14 System.out.println("单个参数无返回值,a = " + a);
15 };
16 methodNoReturnOneParam.lambda2(3);
17
18 // 3、两个参数无返回值
19 MethodNoReturnTwoParam methodNoReturnTwoParam = (int a, int b) -> {
20 System.out.println("两个参数无返回值,a + b = " + (a + b));
21 };
22 methodNoReturnTwoParam.lambda3(3, 4);
23
24 // 4、无参数有返回值
25 MethodReturnNoParam methodReturnNoParam = () -> {
26 return 8;
27 };
28 System.out.println("无参数有返回值:" + methodReturnNoParam.lambda4());
29
30 // 5、一个参数有返回值
31 MethodReturnOneParam methodReturnOneParam = (int a) -> {
32 return a;
33 };
34 System.out.println("一个参数有返回值,a = " + methodReturnOneParam.lambda5(9));
35
36 // 6、一个参数有返回值
37 MethodReturnTwoParam methodReturnTwoParam = (int a, int b) -> {
38 return a + b;
39 };
40 System .out.println("一个参数有返回值,a + b = " + methodReturnTwoParam.lambda6(9, 9));
41
42 }
43
44 /**
45 * 1、无参数无返回值
46 *
47 * @author
48 *
49 */ 50 interface MethodNoReturnNoParam {
51
52 void lambda1();
53 }
54
55 /**
56 * 2、单个参数无返回值
57 *
58 * @author
59 *
60 */ 61 interface MethodNoReturnOneParam {
62
63 void lambda2(int a);
64 }
65
66 /**
67 * 3、两个参数无返回值
68 *
69 * @author
70 *
71 */ 72 interface MethodNoReturnTwoParam {
73
74 void lambda3(int a, int b);
75 }
76
77 /**
78 * 4、无参数有返回值
79 *
80 * @author
81 *
82 */ 83 interface MethodReturnNoParam {
84
85 int lambda4();
86 }
87
88 /**
89 * 5、一个参数有返回值
90 *
91 * @author
92 *
93 */ 94 interface MethodReturnOneParam {
95
96 int lambda5(int a);
97 }
98
99 /**
100 * 6、两个参数有返回值
101 *
102 * @author
103 *
104 */105 interface MethodReturnTwoParam {
106
107 int lambda6(int a, int b);
108 }
109
110 }
5、Lambda表达式语法
精简写法,如下所示:
1)、参数类型可以省略。
2)、假如只有一个参数,()括号可以省略。
3)、如果方法体只有一条语句,{}大括号可以省略。
4)、如果方法体中唯一的语句是return返回语句,那省略大括号的同时return关键词也要省略掉。
1 package com.demo.main;
2
3 public class LambdaMain {
4
5 public static void main(String[] args) {
6 // 1、无参数无返回值
7 MethodNoReturnNoParam methodNoReturnNoParam = () -> System.out.println("无参数无返回值");
8 methodNoReturnNoParam.lambda1();
9
10 // 2、单个参数无返回值
11 MethodNoReturnOneParam methodNoReturnOneParam = a -> System.out.println("单个参数无返回值,a = " + a);
12 methodNoReturnOneParam.lambda2(3);
13
14 // 3、两个参数无返回值
15 MethodNoReturnTwoParam methodNoReturnTwoParam = (a, b) -> System.out.println("两个参数无返回值,a + b = " + (a + b));
16 methodNoReturnTwoParam.lambda3(3, 4);
17
18 // 4、无参数有返回值
19 MethodReturnNoParam methodReturnNoParam = () -> 8;
20 System.out.println("无参数有返回值:" + methodReturnNoParam.lambda4());
21
22 // 5、一个参数有返回值
23 MethodReturnOneParam methodReturnOneParam = a -> a + 10;
24 System.out.println("一个参数有返回值,a = " + methodReturnOneParam.lambda5(9));
25
26 // 6、一个参数有返回值
27 MethodReturnTwoParam methodReturnTwoParam = (a, b) -> a + b;
28 System.out.println("一个参数有返回值,a + b = " + methodReturnTwoParam.lambda6(9, 9));
29
30 }
31
32 /**
33 * 1、无参数无返回值
34 *
35 * @author
36 *
37 */38 interface MethodNoReturnNoParam {
39
40 void lambda1();
41 }
42
43 /**
44 * 2、单个参数无返回值
45 *
46 * @author
47 *
48 */49 interface MethodNoReturnOneParam {
50
51 void lambda2(int a);
52 }
53
54 /**
55 * 3、两个参数无返回值
56 *
57 * @author
58 *
59 */60 interface MethodNoReturnTwoParam {
61
62 void lambda3(int a, int b);
63 }
64
65 /**
66 * 4、无参数有返回值
67 *
68 * @author
69 *
70 */71 interface MethodReturnNoParam {
72
73 int lambda4();
74 }
75
76 /**
77 * 5、一个参数有返回值
78 *
79 * @author
80 *
81 */82 interface MethodReturnOneParam {
83
84 int lambda5(int a);
85 }
86
87 /**
88 * 6、两个参数有返回值
89 *
90 * @author
91 *
92 */93 interface MethodReturnTwoParam {
94
95 int lambda6(int a, int b);
96 }
97
98 }
6、方法引用
如果多个lamdba表达式实现函数都是一样的话,可以封装成通用方法,以方便维护,此时可以使用方法引用实现。
语法规则:对象::方法。假如是static静态方法,可以直接类名::方法。
1 package com.demo.main;
2
3 public class LambdaMain {
4
5 public static void main(String[] args) {
6 // // 创建对象
7 // LambdaMain lambdaMain = new LambdaMain();
8 // // 采用对象引用的方式进行实现
9 // MethodReturnOneParam methodReturnOneParam_1 = lambdaMain::add;
10 // System.out.println(methodReturnOneParam_1.lambda5(10));
11 //
12 // // 采用对象引用的方式进行实现
13 // MethodReturnOneParam methodReturnOneParam_2 = lambdaMain::add;
14 // System.out.println(methodReturnOneParam_2.lambda5(40));
15
16
17 // 创建对象
18 // 采用静态对象引用的方式进行实现
19 MethodReturnOneParam methodReturnOneParam_1 = LambdaMain::addStatic;
20 System.out.println(methodReturnOneParam_1.lambda5(10));
21
22 // 采用静态对象引用的方式进行实现
23 MethodReturnOneParam methodReturnOneParam_2 = LambdaMain::addStatic;
24 System.out.println(methodReturnOneParam_2.lambda5(40));
25 }
26
27 /**
28 * 方法引用,如果多个lamdba表达式实现函数都是一样的话,可以封装成通用方法,以方便维护,此时可以使用方法引用实现。
29 *
30 * @param a
31 * @return
32 */33 public int add(int a) {
34 return a + 10;
35 }
36
37 /**
38 * 静态方法引用
39 *
40 * @param a
41 * @return
42 */43 public static int addStatic(int a) {
44 return a + 10;
45 }
46
47 /**
48 * 5、一个参数有返回值
49 *
50 * @author
51 *
52 */53 interface MethodReturnOneParam {
54
55 int lambda5(int a);
56 }
57
58 }
7、构造方法引用
如果函数式接口的实现切好可以通过调用一个类的构造方法来实现,那么就可以使用构造方法引用。
语法规则:类名::new。
1 package com.demo.po;
2
3 public class Dog {
4
5 private String name;
6 private int age;
7
8 public String getName() {
9 return name;
10 }
11
12 public void setName(String name) {
13 this.name = name;
14 }
15
16 public int getAge() {
17 return age;
18 }
19
20 public void setAge(int age) {
21 this.age = age;
22 }
23
24 @Override
25 public String toString() {
26 return "Dog [name=" + name + ", age=" + age + "]";
27 }
28
29 public Dog(String name, int age) {
30 System.out.println("含参 构造函数 !");
31 this.name = name;
32 this.age = age;
33 }
34
35 public Dog() {
36 System.out.println("无参构造函数!");
37 }
38
39 }
1 package com.demo.main;
2
3 import com.demo.po.Dog;
4
5 public class LambdaMain {
6
7 public static void main(String[] args) {
8 // 1、使用lambda表达式的方式使用
9 DogService dogService1_0 = () -> {
10 return new Dog();
11 };
12 dogService1_0.getDog();
13
14 // 2、简化方式
15 DogService dogService1_1 = () -> new Dog();
16 dogService1_1.getDog();
17
18 // 3、构造方法引用,如果函数式接口的实现切好可以通过调用一个类的构造方法来实现,那么就可以使用构造方法引用。
19 DogService dogService1_2 = Dog::new;
20 dogService1_2.getDog();
21
22 // 4、构造方法引用,有参构造函数调用
23 DogService2 dogService2_1 = Dog::new;
24 dogService2_1.getDog("小黄", 2);
25
26 }
27
28 interface DogService {
29
30 /**
31 * 获取到一只无名狗
32 *
33 * @return
34 */35 Dog getDog();
36 }
37
38 interface DogService2 {
39
40 /**
41 * 获取到一个有名称的狗
42 *
43 * @param name
44 * @param age
45 * @return
46 */47 Dog getDog(String name, int age);
48 }
49
50 }
8、集合使用lambda表达式对数据进行排序,遍历等操作
对于参数是接口函数的方法,需要传递lamdba表达式作为参数进行调用。
1 package com.demo.main;
2
3 import java.util.ArrayList;
4 import java.util.List;
5
6 import com.demo.po.Dog;
7
8 public class LambdaMain {
9
10 public static void main(String[] args) {
11 List<Dog> list = new ArrayList<Dog>();
12 list.add(new Dog("小黄", 5));
13 list.add(new Dog("小花", 4));
14 list.add(new Dog("旺财", 3));
15 list.add(new Dog("团团", 2));
16 list.add(new Dog("圆圆", 1));
17
18 // 排序
19 System.out.println("lambda集合排序!!!");
20 // sort的参数是接口函数,需要使用lambda表达式匿名函数形式
21 list.sort((dog1, dog2) -> dog1.getAge() - dog2.getAge());
22 System.out.println(list);
23 System.out.println();
24
25 // 遍历集合
26 System.out.println("lamdba集合遍历:");
27 list.forEach(System.out::println);
28 }
29
30 }
9、@ function alInterface注解
此注解是函数式接口注解,所谓的函数式接口,当然首先是一个接口,然后就是在这个接口里面只能有一个抽象方法。这种类型的接口也称为SAM接口,即Single Abstract Method interfaces。
特点:
1)、接口有且仅有一个抽象方法。
2)、运行定义静态方法。
3)、允许定义默认方法。
4)、允许java.lang.Object中的public方法。
5)、该注解不是必须的,如果一个接口符合”函数式接口”定义,那么加不加该注解都没有影响。加上该注解能够更好 的 让编译器进行检查。如果编写的不是函数时接口,但是加上该注解,那么编译器会报错。
1 package com.demo.main;
2
3 public class LambdaMain {
4
5 public static void main(String[] args) {
6 FunctionInterface functionInterface = (int a) -> {
7 System.out.println("a = " + a);
8 };
9 functionInterface.add(10);
10 }
11
12 /**
13 * 正确的函数式接口
14 *
15 * @author biexiansheng
16 *
17 */18 @FunctionalInterface
19 interface FunctionInterface {
20
21 /**
22 * 抽象方法
23 */24 public void add(int a);
25
26 /**
27 * java.lang.Object中的public方法
28 *
29 * @param var
30 * @return
31 */32 public boolean equals(Object var);
33
34 // 默认的方法
35 public default void defaultMethod() {
36 System.out.println("默认的方法!!!");
37 }
38
39 // 静态方法
40 public static void staticMethod() {
41 System.out.println("静态的方法!!!");
42 }
43
44 }
45
46 }
10、系统内置函数式接口
Java8的推出,是 以 lamdba重要特性,一起推出的,其中系统内置了一系列函数式接口。在jdk的java.util.function包下,有一系列的内置函数式接口:
1 package com.demo.main;
2
3 import java.util.function.IntConsumer;
4 import java.util.function.IntFunction;
5 import java.util.function.IntPredicate;
6
7 public class LambdaMain {
8
9 public static void main(String[] args) {
10 // 在jdk的java.util.function包下,有一系列的内置函数式接口
11 // 1、使用int函数接口
12 IntFunction<Integer> intFunction = (a) -> {
13 return a + 10;
14 };
15 System.out.println(intFunction.apply(20));
16
17 // 2、使用int判断函数接口
18 final int aa = 20;
19 IntPredicate intPredicate = (a) -> {
20 return a == aa;
21 };
22 System.out.println(intPredicate.test(aa));
23
24 // 3、使用int传递参数的形式
25 IntConsumer intConsumer = (a) -> {
26 System.out.println("a = " + a);
27 };
28 intConsumer.accept(20);
29
30 // 书写技巧:首先定义一个接口函数对象,然后后面跟lambda表达式。
31 // lambda参数列表根据接口函数的方法参数类型和参数个数。
32 // lambda的方法体,是否有返回值,根据接口函数的方法是否有返回值。
33 }
34
35 }