Java8的lambda表达式,通过lambda表达式可以替代我们之前写的匿名内部类来实现接口。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 }
形如(int a, int b) -> {return a + b;},lambda本质就是一个(匿名)函数,匿名函数,就是没有方法名称的函数。
- 1 一般函数结构类似,如下所示:
- 2 int add(int a, int b){
- 3 return a + b;
- 4 }
- 5
- 6 一般函数的,结构如:返回值 方法名称(参数列表) 方法体。
只有参数列表和方法体。结构如:(参数列表) -> {方法体};
详细说明,如下所示:
1)、()括号用来描述参数列表。
2)、{}大括号用来描述方法体。
3)、->尖括号,Lambda运算符,可以叫做箭头符号,或者goes to。
关于接口方法参数、无参、单个参数、两个参数、有返回值、没有返回值的情况。如何来根据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 }

精简写法,如下所示:
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 }
如果多个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 }
如果函数式接口的实现切好可以通过调用一个类的构造方法来实现,那么就可以使用构造方法引用。
语法规则:类名::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 }
对于参数是接口函数的方法,需要传递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 }
此注解是函数式接口注解,所谓的函数式接口,当然首先是一个接口,然后就是在这个接口里面只能有一个抽象方法。这种类型的接口也称为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 }

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 }