Lambda表达式的使用

举例

(o1,o2) -> Integer.compare(o1,o2);

格式

->:lambda操作符 或 箭头操作符
->左边:lambda形参列表(其实就是接口中的抽象方法的形参列表)
->右边:lambda体(其实就是重写的抽象方法的方法体)

  1. public class LambdaTest {
  2. @Test
  3. public void test1(){
  4. Runnable r1 = new Runnable() {
  5. @Override
  6. public void run() {
  7. System.out.println("我爱北京天安门");
  8. }
  9. };
  10. r1.run();
  11. Runnable r2 = () -> System.out.println("我爱北京故宫");
  12. r2.run();
  13. }
  14. @Test
  15. public void test2(){
  16. Comparator<Integer> com1 = new Comparator<Integer>() {
  17. @Override
  18. public int compare(Integer o1, Integer o2) {
  19. return Integer.compare(o1,o2);
  20. }
  21. };
  22. int compare = com1.compare(12, 21);
  23. System.out.println(compare);
  24. //Lambda表达式的写法
  25. Comparator<Integer> com2 = ((o1, o2) -> Integer.compare(o1,o2));
  26. int compare2 = com2.compare(32,23);
  27. System.out.println(compare2);
  28. //方法引用
  29. Comparator<Integer> com3 = Integer :: compare;
  30. int compare3 = com2.compare(32,23);
  31. System.out.println(compare3);
  32. }
  33. }

语法格式(6种)

总结

->左边:lambda形参列表的参数类型可以省略(类型推断),如果lambda形参列表只有一个参数,其一对()也可以省略
->右边:lambda体应该使用一对{}包裹,如果lambda体只有一条执行语句(可能是return语句),可以省略这一对{}和return关键字
屏幕截图 2022-04-20 085458.jpg
屏幕截图 2022-04-20 085536.jpg

  1. //语法格式一:无参,无返回值
  2. @Test
  3. public void test3(){
  4. Runnable r1 = new Runnable() {
  5. @Override
  6. public void run() {
  7. System.out.println("我爱北京天安门");
  8. }
  9. };
  10. r1.run();
  11. Runnable r2 = () -> System.out.println("我爱北京故宫");
  12. r2.run();
  13. }
  14. //语法格式二:Lambda 需要一个参数,但是没有返回值
  15. @Test
  16. public void test4(){
  17. Consumer<String> con = new Consumer<String>() {
  18. @Override
  19. public void accept(String s) {
  20. System.out.println(s);
  21. }
  22. };
  23. con.accept("谎言与誓言的区别");
  24. System.out.println();
  25. Consumer<String> con1 = (String s) -> {
  26. System.out.println(s);
  27. };
  28. con1.accept("一个是听的人当真,一个是说的人当真");
  29. }
  30. //语法格式三:数据类型可以省略,因为可由编译器推断出,称为”类型推断“
  31. @Test
  32. public void test5(){
  33. Consumer<String> con1 = (String s) -> {
  34. System.out.println(s);
  35. };
  36. con1.accept("一个是听的人当真,一个是说的人当真");
  37. System.out.println();
  38. Consumer<String> con2 = (s) -> {
  39. System.out.println(s);
  40. };
  41. con2.accept("一个是听的人当真,一个是说的人当真");
  42. }
  43. //语法格式四:Lambda 若只需要一个参数时,参数的小括号可以省略
  44. @Test
  45. public void test6(){
  46. Consumer<String> con1 = (String s) -> {
  47. System.out.println(s);
  48. };
  49. con1.accept("一个是听的人当真,一个是说的人当真");
  50. System.out.println();
  51. Consumer<String> con2 = s -> {
  52. System.out.println(s);
  53. };
  54. con2.accept("一个是听的人当真,一个是说的人当真");
  55. }
  56. //语法格式五:Lambda 需要两个或两个以上的参数,多条执行语句,并且可以有返回值
  57. @Test
  58. public void test7(){
  59. Comparator<Integer> com1 = new Comparator<Integer>() {
  60. @Override
  61. public int compare(Integer o1, Integer o2) {
  62. System.out.println(o1);
  63. System.out.println(o2);
  64. return o1.compareTo(o2);
  65. }
  66. };
  67. System.out.println(com1.compare(12,21));
  68. System.out.println();
  69. Comparator<Integer> com2 = (o1,o2) -> {
  70. System.out.println(o1);
  71. System.out.println(o2);
  72. return o1.compareTo(o2);
  73. };
  74. System.out.println(com2.compare(2,-1));
  75. }
  76. //语法格式六:当Lambda 体只有一条语句时,return 与大括号若有,都可以省略
  77. @Test
  78. public void test8(){
  79. Comparator<Integer> com1 = (o1,o2) -> {
  80. return o1.compareTo(o2);
  81. };
  82. System.out.println(com1.compare(2,-1));
  83. System.out.println();
  84. Comparator<Integer> com2 = (o1,o2) -> o1.compareTo(o2);
  85. System.out.println(com2.compare(12,6));
  86. }
  87. @Test
  88. public void test9(){
  89. Consumer<String> con1 = s -> {
  90. System.out.println(s);
  91. };
  92. con1.accept("一个是听的人当真,一个是说的人当真");
  93. System.out.println();
  94. Consumer<String> con2 = s -> System.out.println(s);
  95. con2.accept("一个是听的人当真,一个是说的人当真");
  96. }

函数式接口屏幕截图 2022-04-20 150818.jpg

使用

  1. public class LambdaTest1 {
  2. @Test
  3. public void test1(){
  4. happyTime(500, new Consumer<Double>() {
  5. @Override
  6. public void accept(Double aDouble) {
  7. System.out.println("买一瓶水" + aDouble);
  8. }
  9. });
  10. System.out.println();
  11. happyTime(400,money -> System.out.println("买一瓶水" + money));
  12. }
  13. public void happyTime(double money, Consumer<Double> con){
  14. con.accept(money);
  15. }
  16. @Test
  17. public void test2(){
  18. List<String> list = Arrays.asList("新乡","北京","南京","东京","西京");
  19. List<String> filterStrs = filterString(list, new Predicate<String>() {
  20. @Override
  21. public boolean test(String s) {
  22. return s.contains("京");
  23. }
  24. });
  25. System.out.println(filterStrs);
  26. List<String> filterStrs1 = filterString(list,s -> s.contains("新"));
  27. System.out.println(filterStrs1);
  28. }
  29. //根据给定的规则,过滤集合中的字符串。此规则由Predicate的方法决定
  30. public List<String> filterString(List<String> list , Predicate<String> pre){
  31. ArrayList<String> filterList = new ArrayList<>();
  32. for (String s : list){
  33. if (pre.test(s)){
  34. filterList.add(s);
  35. }
  36. }
  37. return filterList;
  38. }
  39. }

方法引用的使用

方法引用,本质上就是Lambda表达式,而Lambda表达式作为函数式接口的实例,所以方法引用,也是函数式接口的实例

使用情景

当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用

格式

类(或对象) ::方法名

三种情况

对象 :: 非静态方法

  1. //情况一:对象 :: 实例方法
  2. @Test
  3. public void test1(){
  4. Consumer<String> con1 = str -> System.out.println(str);
  5. con1.accept("beijing");
  6. System.out.println();
  7. PrintStream ps = System.out;
  8. Consumer<String> con2 = ps :: println;
  9. con2.accept("beijing");
  10. }

类 :: 静态方法

  1. @Test
  2. public void test2(){
  3. Comparator<Integer> com1 = (t1,t2) -> Integer.compare(t1,t2);
  4. System.out.println(com1.compare(12,21));
  5. System.out.println();
  6. Comparator<Integer> com2 = Integer::compare;
  7. System.out.println(com2.compare(12, 3));
  8. }

类 :: 非静态方法

  1. public void test3(){
  2. Comparator<String> com1 = (s1,s2) -> s1.compareTo(s2);
  3. System.out.println(com1.compare("abc", "abd"));
  4. System.out.println();
  5. Comparator<String> com2 = String :: compareTo;
  6. System.out.println(com2.compare("abs","abm"));
  7. }

要求

接口中的抽象方法的形参列表和返回值类型与方法引用的方法的形参列表和返回值类型相同(针对于前两种情况)

数组的引用

  1. @Test
  2. public void test4(){
  3. Function<Integer,String[]> fun1 = length -> new String[length];
  4. String[] arr1 = fun1.apply(5);
  5. System.out.println(Arrays.toString(arr1));
  6. System.out.println();
  7. Function<Integer,String[]> fun2 = String[] ::new;
  8. String[] arr2 = fun2.apply(10);
  9. System.out.println(Arrays.toString(arr2));
  10. }

Stream API

屏幕截图 2022-04-20 212635.jpg
屏幕截图 2022-04-20 212844.jpg

实例化

  1. //创建Stream方式一:通过集合
  2. @Test
  3. public void test1(){
  4. List<Employee> employees = EmployeeDate.getEmployees();
  5. //default Stream<E> stream():返回一个顺序流
  6. Stream<Employee> stream = employees.stream();
  7. //default Stream<E> parallelStream():返回一个并行流
  8. Stream<Employee> parallelStream = employees.parallelStream();
  9. }
  10. //创建Stream方式二:通过数组
  11. @Test
  12. public void test2(){
  13. int[] arr = new int[]{1,2,3,4,5};
  14. //调用Arrays类的static<T> Stream<T> stream(T[] array):返回一个流
  15. IntStream stream = Arrays.stream(arr);
  16. Employee e1 = new Employee(100,"Tom");
  17. Employee e2 = new Employee(100,"Jerry");
  18. Employee[] arr1 = new Employee[]{e1,e2};
  19. Stream<Employee> stream1 = Arrays.stream(arr1);
  20. }
  21. //创建Stream方式三:通过Stream的of()
  22. @Test
  23. public void test3(){
  24. Stream<Integer> stream = Stream.of(1,2,3,4);
  25. }

中间操作

屏幕截图 2022-04-21 112939.jpg
屏幕截图 2022-04-21 113023.jpg
屏幕截图 2022-04-21 210958.jpg

终止操作

屏幕截图 2022-04-21 211304.jpg
屏幕截图 2022-04-21 211640.jpg
屏幕截图 2022-04-21 212023.jpg

Optional类

屏幕截图 2022-04-21 212711.jpg