1.基础语法

Java8中引入了一个新的操作符 “->” 该操作符称为箭头操作符或 Lambda 操作符。
箭头操作符将 Lambda 表达式拆分成两部分:
左侧:Lambda 表达式的参数列表
右侧:Lambda 表达式中所需执行的功能,既 Lambda 体

(1)语法格式一:无参数,无返回值

  1. () -> System.out.println("Hello Lambda!")

(2)语法格式二:有一个参数,无返回值

  1. (x) -> System.out.println(x)

(3)语法格式三:仅有一个参数,小括号可以省略

  1. x -> System.out.println(x)

(4)语法格式四:两个及以上参数,有返回值,且 Lambda 体中有多条语句

  1. Comparator<Integer> com = (x,y)-> {
  2. System.out.println("Hello Lambda!");
  3. return Integer.compare(x, y);
  4. };

(5)语法格式五:Lambda 体中仅有一条语句,return 和大括号都可省略

  1. Comparator<Integer> com = (x,y)-> Integer.compare(x, y);

(6)语法格式六:Lambda 表达式的参数列表的数据类型可省略不写,因为JVM编译器通过上下文进行”类型推断”

  1. (Integer x,Integer y)-> Integer.compare(x, y);

Lambda心法:
上联:左右遇一括号省
下联:左侧推断类型省
横批:能省则省

2.函数式接口

2.1 定义

函数式接口中只有一个抽象方法。可以使用注解@FunctionalInterface 修饰

2.2 Java内置四大核心函数式接口

函数式接口 参数类型 返回类型 用途
Consumer
消费型接口
T void 对类型为T的对象应用操作:void accept(T t)
Supplier
提供型接口
T 返回类型为T的对象:T get()
Function
函数型接口
T R 对类型为T的对象应用操作,并返回结果为R类型的对象:R apply(T t)
Predicate
断言型接口
T boolean 确定类型为T的对象是否满足某约束,并返回boolean值:boolean test(T t)

2.3 四大核心接口衍生接口

20200518225311406.png
示例代码:

  1. package cn.mineye.feature.java8;
  2. import org.junit.jupiter.api.Test;
  3. import org.springframework.boot.test.context.SpringBootTest;
  4. import java.util.ArrayList;
  5. import java.util.Arrays;
  6. import java.util.List;
  7. import java.util.function.Consumer;
  8. import java.util.function.Function;
  9. import java.util.function.Predicate;
  10. import java.util.function.Supplier;
  11. /**
  12. * <p>
  13. * Lambda内置核心接口测试
  14. * </p>
  15. *
  16. * @author 571
  17. * @since 2021/7/24
  18. */
  19. @SpringBootTest
  20. public class LambdaTest {
  21. //Consumer<T> 消费型接口,只进不出
  22. @Test
  23. public void test1() {
  24. donate(100.00, (m) -> System.out.println("捐赠:" + m + "元"));
  25. }
  26. public void donate(double money, Consumer<Double> con) {
  27. con.accept(money);
  28. }
  29. //Supplier<T> 供给型接口,不进有出
  30. @Test
  31. public void test2() {
  32. List<Double> list = shitLuck(2, () -> Math.random() * 100);
  33. for (Double num : list) {
  34. System.out.println("不劳而获:" + num + "元");
  35. }
  36. }
  37. public List<Double> shitLuck(int num, Supplier<Double> sup) {
  38. List<Double> list = new ArrayList<>();
  39. for (int i = 0; i < num; i++) {
  40. Double n = sup.get();
  41. list.add(n);
  42. }
  43. return list;
  44. }
  45. //Function<T, R> 函数型接口:有进有出
  46. @Test
  47. public void test3() {
  48. String str = work(8D, (h) -> h * 100 + " 元");
  49. System.out.println("今天工作8小时,老板给我工钱:" + str);
  50. }
  51. public String work(Double hour, Function<Double, String> fun) {
  52. return fun.apply(hour);
  53. }
  54. //Predicate<T> 断言型接口:有进有判断
  55. @Test
  56. public void test4() {
  57. List<String> list = Arrays.asList("bird", "house", "monkey", "tiger", "dog");
  58. List<String> strList = filterStr(list, (s) -> s.length() > 4);
  59. for (String str : strList) {
  60. System.out.println("长度大于4的单词:" + str);
  61. }
  62. }
  63. public List<String> filterStr(List<String> list, Predicate<String> pre) {
  64. List<String> strList = new ArrayList<>();
  65. for (String str : list) {
  66. if (pre.test(str)) {
  67. strList.add(str);
  68. }
  69. }
  70. return strList;
  71. }
  72. }

3.引用

定义:若 Lambda 表达式体中的内容已有方法实现,则可以使用“方法引用”

3.1 方法引用

语法格式:

  • 对象 :: 实例方法
  • 类 :: 静态方法
  • 类 :: 实例方法

(1)对象::实例方法
注意:Lambda 表达式体中调用方法的参数列表返回类型必须和函数式接口中抽象方法保持一致

  1. @Test
  2. public void test01(){
  3. PrintStream ps = System.out;
  4. Consumer<String> con1 = (s) -> ps.println(s);
  5. con1.accept("aaa");
  6. //对象::实例方法 表示
  7. Consumer<String> con2 = ps::println;
  8. con2.accept("bbb");
  9. }

(2)类::静态方法

  1. @Test
  2. public void test02(){
  3. Comparator<Integer> com1 = (x, y) -> Integer.compare(x, y);
  4. System.out.println(com1.compare(1, 2));
  5. //类::静态方法 表示
  6. Comparator<Integer> com2 = Integer::compare;
  7. System.out.println(com2.compare(2, 1));
  8. }

(3)类::实例方法
注意:Lambda 参数列表中的第一个参数是方法的调用者第二个参数是方法的参数时,才能使用 类::实例方法

  1. @Test
  2. public void test03(){
  3. BiPredicate<String, String> bp1 = (x, y) -> x.equals(y);
  4. System.out.println(bp1.test("a","b"));
  5. //类::实例方法 表示
  6. BiPredicate<String, String> bp2 = String::equals;
  7. System.out.println(bp2.test("c","c"));
  8. }

3.2 构造器引用

语法格式:
类名::new

类名::new
注意:需要调用的构造器的参数列表要与函数式接口中抽象方法的参数列表保持一致

  1. @Test
  2. public void test04(){
  3. Supplier<List> sup1 = () -> new ArrayList();
  4. //类名::new 表示
  5. Supplier<List> sup2 = ArrayList::new;
  6. }

3.3 数组引用

语法格式:
Type::new

Type::new

  1. @Test
  2. public void test05() {
  3. Function<Integer,String[]> fun=x ->new String[x];
  4. String[] str=fun.apply(3);
  5. //Type::new 表示
  6. Function<Integer,String[]> fun2=String[]::new;
  7. String[] str2=fun.apply(4);
  8. }