• Java8方法引用和Lambda表达式实例源码+笔记分享


    前言

    Java8的lambda表达式,通过lambda表达式可以替代我们之前写的匿名内部类来实现接口。lambda表达式本质是一个匿名函数。

    1、lambda表达式本质是一个匿名函数。

    1. 1 package com.demo.main;
    2. 2
    3. 3 public class LambdaMain {
    4. 4
    5. 5 public static void main(String[] args) {
    6. 6
    7. 7 // 1、创建一个匿名内部类
    8. 8 Addition addition = new Addition() {
    9. 9
    10. 10 @Override
    11. 11 public int add(int a, int b) {
    12. 12
    13. 13 return a + b;
    14. 14 }
    15. 15
    16. 16 };
    17. 17 // 传统的匿名内部类来实现接口。
    18. 18 System.out.println("调用匿名内部类来实现接口:" + addition.add(2, 3));
    19. 19
    20. 20 // 2、Java8的lambda表达式,通过lambda表达式可以替代我们之前写的匿名内部类来实现接口。
    21. 21 // lambda表达式本质是一个匿名函数。
    22. 22 // 2.1、lambda由三部分组成,()是参数列表,->剪头符号,{}代表方法体。
    23. 23 Addition a2 = (int a, int b) -> {
    24. 24 return a + b;
    25. 25 };
    26. 26 System.out.println("lambda表达式a2:" + a2.add(3, 3));
    27. 27
    28. 28 // 2.2、可以省略参数列表里面的参数类型
    29. 29 Addition a3 = (a, b) -> {
    30. 30 return a + b;
    31. 31 };
    32. 32 System.out.println("lambda表达式a3:" + a3.add(3, 3));
    33. 33
    34. 34 }
    35. 35
    36. 36 /**
    37. 37 *
    38. 38 * @author 创建一个接口,定义一个方法
    39. 39 *
    40. 40 */
    41. 41 interface Addition {
    42. 42
    43. 43 /**
    44. 44 * 加法的方法
    45. 45 *
    46. 46 * @param a
    47. 47 * @param b
    48. 48 * @return
    49. 49 */
    50. 50 int add(int a, int b);
    51. 51 }
    52. 52
    53. 53 }

    2、Lambda表达式语法

    形如(int a, int b) -> {return a + b;},lambda本质就是一个(匿名)函数,匿名函数,就是没有方法名称的函数。

    1. 1 一般函数结构类似,如下所示:
    2. 2 int add(int a, int b){
    3. 3 return a + b;
    4. 4 }
    5. 5
    6. 6 一般函数的,结构如:返回值 方法名称(参数列表) 方法体。

    3、而Lamdba表达式函数

    只有参数列表和方法体。结构如:(参数列表) -> {方法体};

    详细说明,如下所示:

      1)、()括号用来描述参数列表。
      2)、{}大括号用来描述方法体。
      3)、->尖括号,Lambda运算符,可以叫做箭头符号,或者goes to。

    4、Lambda表达式语法

    关于接口方法参数、无参、单个参数、两个参数、有返回值、没有返回值的情况。如何来根据lambda来返回接口函数。

    1. 1 package com.demo.main;
    2. 2
    3. 3 public class LambdaMain {
    4. 4
    5. 5 public static void main(String[] args) {
    6. 6 // 1、无参数无返回值
    7. 7 MethodNoReturnNoParam methodNoReturnNoParam = () -> {
    8. 8 System.out.println("无参数无返回值");
    9. 9 };
    10. 10 methodNoReturnNoParam.lambda1();
    11. 11
    12. 12 // 2、单个参数无返回值
    13. 13 MethodNoReturnOneParam methodNoReturnOneParam = (int a) -> {
    14. 14 System.out.println("单个参数无返回值,a = " + a);
    15. 15 };
    16. 16 methodNoReturnOneParam.lambda2(3);
    17. 17
    18. 18 // 3、两个参数无返回值
    19. 19 MethodNoReturnTwoParam methodNoReturnTwoParam = (int a, int b) -> {
    20. 20 System.out.println("两个参数无返回值,a + b = " + (a + b));
    21. 21 };
    22. 22 methodNoReturnTwoParam.lambda3(3, 4);
    23. 23
    24. 24 // 4、无参数有返回值
    25. 25 MethodReturnNoParam methodReturnNoParam = () -> {
    26. 26 return 8;
    27. 27 };
    28. 28 System.out.println("无参数有返回值:" + methodReturnNoParam.lambda4());
    29. 29
    30. 30 // 5、一个参数有返回值
    31. 31 MethodReturnOneParam methodReturnOneParam = (int a) -> {
    32. 32 return a;
    33. 33 };
    34. 34 System.out.println("一个参数有返回值,a = " + methodReturnOneParam.lambda5(9));
    35. 35
    36. 36 // 6、一个参数有返回值
    37. 37 MethodReturnTwoParam methodReturnTwoParam = (int a, int b) -> {
    38. 38 return a + b;
    39. 39 };
    40. 40 System.out.println("一个参数有返回值,a + b = " + methodReturnTwoParam.lambda6(9, 9));
    41. 41
    42. 42 }
    43. 43
    44. 44 /**
    45. 45 * 1、无参数无返回值
    46. 46 *
    47. 47 * @author
    48. 48 *
    49. 49 */
    50. 50 interface MethodNoReturnNoParam {
    51. 51
    52. 52 void lambda1();
    53. 53 }
    54. 54
    55. 55 /**
    56. 56 * 2、单个参数无返回值
    57. 57 *
    58. 58 * @author
    59. 59 *
    60. 60 */
    61. 61 interface MethodNoReturnOneParam {
    62. 62
    63. 63 void lambda2(int a);
    64. 64 }
    65. 65
    66. 66 /**
    67. 67 * 3、两个参数无返回值
    68. 68 *
    69. 69 * @author
    70. 70 *
    71. 71 */
    72. 72 interface MethodNoReturnTwoParam {
    73. 73
    74. 74 void lambda3(int a, int b);
    75. 75 }
    76. 76
    77. 77 /**
    78. 78 * 4、无参数有返回值
    79. 79 *
    80. 80 * @author
    81. 81 *
    82. 82 */
    83. 83 interface MethodReturnNoParam {
    84. 84
    85. 85 int lambda4();
    86. 86 }
    87. 87
    88. 88 /**
    89. 89 * 5、一个参数有返回值
    90. 90 *
    91. 91 * @author
    92. 92 *
    93. 93 */
    94. 94 interface MethodReturnOneParam {
    95. 95
    96. 96 int lambda5(int a);
    97. 97 }
    98. 98
    99. 99 /**
    100. 100 * 6、两个参数有返回值
    101. 101 *
    102. 102 * @author
    103. 103 *
    104. 104 */
    105. 105 interface MethodReturnTwoParam {
    106. 106
    107. 107 int lambda6(int a, int b);
    108. 108 }
    109. 109
    110. 110 }

    5、Lambda表达式语法

    精简写法,如下所示:

      1)、参数类型可以省略。
      2)、假如只有一个参数,()括号可以省略。
      3)、如果方法体只有一条语句,{}大括号可以省略。
      4)、如果方法体中唯一的语句是return返回语句,那省略大括号的同时return关键词也要省略掉。

    1. 1 package com.demo.main;
    2. 2
    3. 3 public class LambdaMain {
    4. 4
    5. 5 public static void main(String[] args) {
    6. 6 // 1、无参数无返回值
    7. 7 MethodNoReturnNoParam methodNoReturnNoParam = () -> System.out.println("无参数无返回值");
    8. 8 methodNoReturnNoParam.lambda1();
    9. 9
    10. 10 // 2、单个参数无返回值
    11. 11 MethodNoReturnOneParam methodNoReturnOneParam = a -> System.out.println("单个参数无返回值,a = " + a);
    12. 12 methodNoReturnOneParam.lambda2(3);
    13. 13
    14. 14 // 3、两个参数无返回值
    15. 15 MethodNoReturnTwoParam methodNoReturnTwoParam = (a, b) -> System.out.println("两个参数无返回值,a + b = " + (a + b));
    16. 16 methodNoReturnTwoParam.lambda3(3, 4);
    17. 17
    18. 18 // 4、无参数有返回值
    19. 19 MethodReturnNoParam methodReturnNoParam = () -> 8;
    20. 20 System.out.println("无参数有返回值:" + methodReturnNoParam.lambda4());
    21. 21
    22. 22 // 5、一个参数有返回值
    23. 23 MethodReturnOneParam methodReturnOneParam = a -> a + 10;
    24. 24 System.out.println("一个参数有返回值,a = " + methodReturnOneParam.lambda5(9));
    25. 25
    26. 26 // 6、一个参数有返回值
    27. 27 MethodReturnTwoParam methodReturnTwoParam = (a, b) -> a + b;
    28. 28 System.out.println("一个参数有返回值,a + b = " + methodReturnTwoParam.lambda6(9, 9));
    29. 29
    30. 30 }
    31. 31
    32. 32 /**
    33. 33 * 1、无参数无返回值
    34. 34 *
    35. 35 * @author
    36. 36 *
    37. 37 */
    38. 38 interface MethodNoReturnNoParam {
    39. 39
    40. 40 void lambda1();
    41. 41 }
    42. 42
    43. 43 /**
    44. 44 * 2、单个参数无返回值
    45. 45 *
    46. 46 * @author
    47. 47 *
    48. 48 */
    49. 49 interface MethodNoReturnOneParam {
    50. 50
    51. 51 void lambda2(int a);
    52. 52 }
    53. 53
    54. 54 /**
    55. 55 * 3、两个参数无返回值
    56. 56 *
    57. 57 * @author
    58. 58 *
    59. 59 */
    60. 60 interface MethodNoReturnTwoParam {
    61. 61
    62. 62 void lambda3(int a, int b);
    63. 63 }
    64. 64
    65. 65 /**
    66. 66 * 4、无参数有返回值
    67. 67 *
    68. 68 * @author
    69. 69 *
    70. 70 */
    71. 71 interface MethodReturnNoParam {
    72. 72
    73. 73 int lambda4();
    74. 74 }
    75. 75
    76. 76 /**
    77. 77 * 5、一个参数有返回值
    78. 78 *
    79. 79 * @author
    80. 80 *
    81. 81 */
    82. 82 interface MethodReturnOneParam {
    83. 83
    84. 84 int lambda5(int a);
    85. 85 }
    86. 86
    87. 87 /**
    88. 88 * 6、两个参数有返回值
    89. 89 *
    90. 90 * @author
    91. 91 *
    92. 92 */
    93. 93 interface MethodReturnTwoParam {
    94. 94
    95. 95 int lambda6(int a, int b);
    96. 96 }
    97. 97
    98. 98 }

    6、方法引用

    如果多个lamdba表达式实现函数都是一样的话,可以封装成通用方法,以方便维护,此时可以使用方法引用实现。

      语法规则:对象::方法。假如是static静态方法,可以直接类名::方法。

    1. 1 package com.demo.main;
    2. 2
    3. 3 public class LambdaMain {
    4. 4
    5. 5 public static void main(String[] args) {
    6. 6 // // 创建对象
    7. 7 // LambdaMain lambdaMain = new LambdaMain();
    8. 8 // // 采用对象引用的方式进行实现
    9. 9 // MethodReturnOneParam methodReturnOneParam_1 = lambdaMain::add;
    10. 10 // System.out.println(methodReturnOneParam_1.lambda5(10));
    11. 11 //
    12. 12 // // 采用对象引用的方式进行实现
    13. 13 // MethodReturnOneParam methodReturnOneParam_2 = lambdaMain::add;
    14. 14 // System.out.println(methodReturnOneParam_2.lambda5(40));
    15. 15
    16. 16
    17. 17 // 创建对象
    18. 18 // 采用静态对象引用的方式进行实现
    19. 19 MethodReturnOneParam methodReturnOneParam_1 = LambdaMain::addStatic;
    20. 20 System.out.println(methodReturnOneParam_1.lambda5(10));
    21. 21
    22. 22 // 采用静态对象引用的方式进行实现
    23. 23 MethodReturnOneParam methodReturnOneParam_2 = LambdaMain::addStatic;
    24. 24 System.out.println(methodReturnOneParam_2.lambda5(40));
    25. 25 }
    26. 26
    27. 27 /**
    28. 28 * 方法引用,如果多个lamdba表达式实现函数都是一样的话,可以封装成通用方法,以方便维护,此时可以使用方法引用实现。
    29. 29 *
    30. 30 * @param a
    31. 31 * @return
    32. 32 */
    33. 33 public int add(int a) {
    34. 34 return a + 10;
    35. 35 }
    36. 36
    37. 37 /**
    38. 38 * 静态方法引用
    39. 39 *
    40. 40 * @param a
    41. 41 * @return
    42. 42 */
    43. 43 public static int addStatic(int a) {
    44. 44 return a + 10;
    45. 45 }
    46. 46
    47. 47 /**
    48. 48 * 5、一个参数有返回值
    49. 49 *
    50. 50 * @author
    51. 51 *
    52. 52 */
    53. 53 interface MethodReturnOneParam {
    54. 54
    55. 55 int lambda5(int a);
    56. 56 }
    57. 57
    58. 58 }

    7、构造方法引用

    如果函数式接口的实现切好可以通过调用一个类的构造方法来实现,那么就可以使用构造方法引用。

    语法规则:类名::new。

    1. 1 package com.demo.po;
    2. 2
    3. 3 public class Dog {
    4. 4
    5. 5 private String name;
    6. 6 private int age;
    7. 7
    8. 8 public String getName() {
    9. 9 return name;
    10. 10 }
    11. 11
    12. 12 public void setName(String name) {
    13. 13 this.name = name;
    14. 14 }
    15. 15
    16. 16 public int getAge() {
    17. 17 return age;
    18. 18 }
    19. 19
    20. 20 public void setAge(int age) {
    21. 21 this.age = age;
    22. 22 }
    23. 23
    24. 24 @Override
    25. 25 public String toString() {
    26. 26 return "Dog [name=" + name + ", age=" + age + "]";
    27. 27 }
    28. 28
    29. 29 public Dog(String name, int age) {
    30. 30 System.out.println("含参构造函数!");
    31. 31 this.name = name;
    32. 32 this.age = age;
    33. 33 }
    34. 34
    35. 35 public Dog() {
    36. 36 System.out.println("无参构造函数!");
    37. 37 }
    38. 38
    39. 39 }
    1. 1 package com.demo.main;
    2. 2
    3. 3 import com.demo.po.Dog;
    4. 4
    5. 5 public class LambdaMain {
    6. 6
    7. 7 public static void main(String[] args) {
    8. 8 // 1、使用lambda表达式的方式使用
    9. 9 DogService dogService1_0 = () -> {
    10. 10 return new Dog();
    11. 11 };
    12. 12 dogService1_0.getDog();
    13. 13
    14. 14 // 2、简化方式
    15. 15 DogService dogService1_1 = () -> new Dog();
    16. 16 dogService1_1.getDog();
    17. 17
    18. 18 // 3、构造方法引用,如果函数式接口的实现切好可以通过调用一个类的构造方法来实现,那么就可以使用构造方法引用。
    19. 19 DogService dogService1_2 = Dog::new;
    20. 20 dogService1_2.getDog();
    21. 21
    22. 22 // 4、构造方法引用,有参构造函数调用
    23. 23 DogService2 dogService2_1 = Dog::new;
    24. 24 dogService2_1.getDog("小黄", 2);
    25. 25
    26. 26 }
    27. 27
    28. 28 interface DogService {
    29. 29
    30. 30 /**
    31. 31 * 获取到一只无名狗
    32. 32 *
    33. 33 * @return
    34. 34 */
    35. 35 Dog getDog();
    36. 36 }
    37. 37
    38. 38 interface DogService2 {
    39. 39
    40. 40 /**
    41. 41 * 获取到一个有名称的狗
    42. 42 *
    43. 43 * @param name
    44. 44 * @param age
    45. 45 * @return
    46. 46 */
    47. 47 Dog getDog(String name, int age);
    48. 48 }
    49. 49
    50. 50 }

    8、集合使用lambda表达式对数据进行排序,遍历等操作

    对于参数是接口函数的方法,需要传递lamdba表达式作为参数进行调用。

    1. 1 package com.demo.main;
    2. 2
    3. 3 import java.util.ArrayList;
    4. 4 import java.util.List;
    5. 5
    6. 6 import com.demo.po.Dog;
    7. 7
    8. 8 public class LambdaMain {
    9. 9
    10. 10 public static void main(String[] args) {
    11. 11 List<Dog> list = new ArrayList<Dog>();
    12. 12 list.add(new Dog("小黄", 5));
    13. 13 list.add(new Dog("小花", 4));
    14. 14 list.add(new Dog("旺财", 3));
    15. 15 list.add(new Dog("团团", 2));
    16. 16 list.add(new Dog("圆圆", 1));
    17. 17
    18. 18 // 排序
    19. 19 System.out.println("lambda集合排序!!!");
    20. 20 // sort的参数是接口函数,需要使用lambda表达式匿名函数形式
    21. 21 list.sort((dog1, dog2) -> dog1.getAge() - dog2.getAge());
    22. 22 System.out.println(list);
    23. 23 System.out.println();
    24. 24
    25. 25 // 遍历集合
    26. 26 System.out.println("lamdba集合遍历:");
    27. 27 list.forEach(System.out::println);
    28. 28 }
    29. 29
    30. 30 }

    9、@FunctionalInterface注解

    此注解是函数式接口注解,所谓的函数式接口,当然首先是一个接口,然后就是在这个接口里面只能有一个抽象方法。这种类型的接口也称为SAM接口,即Single Abstract Method interfaces。
    特点:

      1)、接口有且仅有一个抽象方法。
      2)、运行定义静态方法。
      3)、允许定义默认方法。
      4)、允许java.lang.Object中的public方法。
      5)、该注解不是必须的,如果一个接口符合"函数式接口"定义,那么加不加该注解都没有影响。加上该注解能够更好的让编译器进行检查。如果编写的不是函数时接口,但是加上该注解,那么编译器会报错。

    1. 1 package com.demo.main;
    2. 2
    3. 3 public class LambdaMain {
    4. 4
    5. 5 public static void main(String[] args) {
    6. 6 FunctionInterface functionInterface = (int a) -> {
    7. 7 System.out.println("a = " + a);
    8. 8 };
    9. 9 functionInterface.add(10);
    10. 10 }
    11. 11
    12. 12 /**
    13. 13 * 正确的函数式接口
    14. 14 *
    15. 15 * @author biexiansheng
    16. 16 *
    17. 17 */
    18. 18 @FunctionalInterface
    19. 19 interface FunctionInterface {
    20. 20
    21. 21 /**
    22. 22 * 抽象方法
    23. 23 */
    24. 24 public void add(int a);
    25. 25
    26. 26 /**
    27. 27 * java.lang.Object中的public方法
    28. 28 *
    29. 29 * @param var
    30. 30 * @return
    31. 31 */
    32. 32 public boolean equals(Object var);
    33. 33
    34. 34 // 默认的方法
    35. 35 public default void defaultMethod() {
    36. 36 System.out.println("默认的方法!!!");
    37. 37 }
    38. 38
    39. 39 // 静态方法
    40. 40 public static void staticMethod() {
    41. 41 System.out.println("静态的方法!!!");
    42. 42 }
    43. 43
    44. 44 }
    45. 45
    46. 46 }

    10、系统内置函数式接口

    Java8的推出,是以lamdba重要特性,一起推出的,其中系统内置了一系列函数式接口。在jdk的java.util.function包下,有一系列的内置函数式接口:

    1. 1 package com.demo.main;
    2. 2
    3. 3 import java.util.function.IntConsumer;
    4. 4 import java.util.function.IntFunction;
    5. 5 import java.util.function.IntPredicate;
    6. 6
    7. 7 public class LambdaMain {
    8. 8
    9. 9 public static void main(String[] args) {
    10. 10 // 在jdk的java.util.function包下,有一系列的内置函数式接口
    11. 11 // 1、使用int函数接口
    12. 12 IntFunction<Integer> intFunction = (a) -> {
    13. 13 return a + 10;
    14. 14 };
    15. 15 System.out.println(intFunction.apply(20));
    16. 16
    17. 17 // 2、使用int判断函数接口
    18. 18 final int aa = 20;
    19. 19 IntPredicate intPredicate = (a) -> {
    20. 20 return a == aa;
    21. 21 };
    22. 22 System.out.println(intPredicate.test(aa));
    23. 23
    24. 24 // 3、使用int传递参数的形式
    25. 25 IntConsumer intConsumer = (a) -> {
    26. 26 System.out.println("a = " + a);
    27. 27 };
    28. 28 intConsumer.accept(20);
    29. 29
    30. 30 // 书写技巧:首先定义一个接口函数对象,然后后面跟lambda表达式。
    31. 31 // lambda参数列表根据接口函数的方法参数类型和参数个数。
    32. 32 // lambda的方法体,是否有返回值,根据接口函数的方法是否有返回值。
    33. 33 }
    34. 34
    35. 35 }
  • 相关阅读:
    指针进阶---指针数组,数组指针
    洛谷 P4197&&P7834 Peaks 题解
    C++标准模板(STL)- 类型支持 ()
    基于springboot实现家具销售电商平台管理系统项目【项目源码+论文说明】
    Diffusion Autoencoders: Toward a Meaningful and Decodable Representation
    金仓数据库 KingbaseES 插件参考手册 zhparser
    C语言-结构体
    贪吃蛇案例
    解决idea运行maven项目报错Unresolved plugin ‘org.apache.maven.pluginsxxxx
    C#在winform 控制台输出 cmd窗口
  • 原文地址:https://blog.csdn.net/Java_zhujia/article/details/127864114