转载

Java 8 --- Lambda表达式

一、前言

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

二、Lambda表达式语法

  • 2.1 语法

    (paramaters) -> expression
    (paramaters) -> {expression;}
    
  • 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)未完......
原文  https://segmentfault.com/a/1190000019818017
正文到此结束
Loading...