乐趣区

Java-8-Lambda表达式

一、前言

  • Lambda 表达式是在 Java8 中引入的,并号称是 Java8 的最大的特点.
  • Lambda 表达式有利于函数式编程,简化了开发了很多。
  • 允许把函数作为一个方法的 参数(函数作为参数传递进方法中)
  • λ 表达式本质上是一个匿名方法

二、Lambda 表达式语法

  • 2.1 语法

    • (paramaters) -> expression(表达式)
    • (paramaters) -> statement(语句)
    • (paramaters) -> {expression/statement;}

  • 2.2 特征

    • (1)、可选类型声明 – 无需声明参数的类型。编译器可以从该参数的值推断。
    • (2)、可选圆括号参数 – 无需在括号中声明参数。对于多个参数,括号是必需的。
    • (3)、可选大括号 – 表达式主体没有必要使用大括号,如果主体中含有一个单独的语句。
    • (4)、可选 return 关键字 – 编译器会自动返回值,如果主体有一个表达式返回的值。花括号是必需的,以表明表达式返回一个值。

  • 2.3 例子

    public int addition(int a, int b) {return a + b;}
    
    //lambda 表达式写法 1
    (int a, int b) -> a + b
    
    //lambda 表达式写法 2
    (int a, int b) -> {return a + b;}
    
    //lambda 表达式写法 3 (自动推断参数类型)
    (a, b) -> a + b;
    • lambda 公式(参数列表) -> {表达式;}

  • 2.4 Lambda 的类型

    • 2.4.1 λ 表达式返回值类型是的目标类型,目标类型是 ” 函数接口(functional interface)”

      • 函数接口 :一个只含有显式声明的 抽象方法 的接口。

        public interface Runnable {void run();}
        public interface Comparator<T> {int compare(T o1, T o2); 
                boolean equals(Object obj); }
      • 注:第二个接口也是函数接口,因为 equals 方法是 Object 的,
        所有的接口都会声明 Object 的 public 方法——虽然大多是 隐式的 ,只不过 Comparator 显式的声明 了 equals
    • 2.4.2 用 Lambda 表达式赋值

      • 可以用一个 λ 表达式为一个函数接口赋值:

        //(1)
        Runnable r1 = () -> { System.out.println("Lambda!");};
        Object obj = r1;
        //(2)错误例子
        Object obj = () -> {System.out.println("Lambda!");}; 
        // 错误:对象不是函数接口!//(3)必须显式的转型成一个函数接口才可以
        Object obj = (Runnable)()->System.out.println("Lambda!");}; 
      • λ 表达式只有在转型成一个函数接口后才能被当做 Object 使用

        System.out.println(() -> {}); // 错误! 目标类型不明
        System.out.println((Runnable)() -> {} ); // 正确
      • 自定义函数接口

        @FunctionalInterface
        public interface MyFuntionInterface {public void doSomething();
        }
        Runnable r1 = ()->{System.out.println("Runnbale");};
        MyFuntionInterface m2 = ()->{System.out.println("MyFI");}
        • 都是正确的写法。这说明一个 λ 表达式可以有 多个 目标类型 (函数接口), 只要函数 匹配成功 即可。但需注意一个 λ 表达式必须 至少有一个 目标类型 */

三、Lambda 表达式的用处

  • (1)、用于替换以前广泛使用的内部匿名类

    • 内部匿名类写法
      Thread t1 = new Thread (new Runnable(){

      @Override
      public void run() {System.out.println("匿名内部类写法");
      }

      });

    • Lambda 表达式写法

      Thread t2 = new Thread (()->{System.out.println("Lambda 表达式写法"); } );
      • 注意:第 2 个线程里的 λ 表达式,你并不需要显式地把它转成一个 Runnable,因为 Java 能根据上下文自动推断出来:一个 Thread 的构造函数接受一个 Runnable 参数,而传入的 λ 表达式正好符合其 run()函数,所以 Java 编译器推断它为 Runnable
  • (2)、 λ 表达式与集合类批处理操作(或者叫块操作)

    • 集合类的迭代分为

      List<String> list = new ArrayList<>() {"AA", "BB", "CC"};
      • 外部迭代:由客户代码进行迭代

        for(Object o : list) { // 外部迭代
            System.out.println(o);
        }
      • 内部迭代:由 Java 类库来进行迭代

        list.forEach(o -> {System.out.println(o);});
      • forEach方法接受一个函数接口 Consumer 做参数,故可以使用 λ 表达式
  • (3)未完......
退出移动版