Lambda表达式

Posted by lily on April 7, 2023

lambda表达式

函数式接口

  1. 只包含一个抽象方法的接口,称为函数式接口
    @FunctionalInterface
    interface myInterface{
        xxx absMethod();
    }
    
  2. 你可以通过 Lambda 表达式来创建该接口的对象。(若 Lambda 表达式抛出一个受检异常(即:非运行时异常),那么该异常需要在目标接口的抽象方法上进行声明)。
  3. 我们可以在一个接口上使用 **@FunctionalInterface **注解,这样做可以检查它是否是一个函数式接口。同时 javadoc 也会包含一条声明,说明这个接口是一个函数式接口。
  4. 在java.util.function包下定义了Java 8 的丰富的函数式接口
  5. 例如**Consumer **

**Consumer消费型接口 **T void 对类型为T的对象应用操作,包含方法: **void accept(T t) **
**Supplier 供给型接口 **无 T 返回类型为T的对象,包含方法:**T get() **
**Function<T, R> 函数型接口 **T R 对类型为T的对象应用操作,并返回结果结 果是R类型的对象。包含方法:**R apply(T t) **
**Predicate 断定型接口 **T boolean 确定类型为T的对象是否满足某约束,并返回boolean 值。包含方法:**boolean test(T t)**
![image.png](https://cdn.nlark.com/yuque/0/2022/png/1238904/1669818137775-db30fbcd-d22f-4d06-9016-6d8f3f6129b9.png#averageHue=%238a9bb0&clientId=ubc53689a-662e-4&from=paste&height=315&id=uf90876c7&name=image.png&originHeight=473&originWidth=853&originalType=binary&ratio=1&rotation=0&showTitle=false&size=165319&status=done&style=none&taskId=u07fce2dd-b5bb-4e19-8eb6-ce5ad69e270&title=&width=568.6666666666666)

匿名对象

  1. 当我们想使用该函数式接口的抽象方法时,可以实时创建一个接口实现类,不过这样会使得事情变得麻烦一些,并且代码量较大,但核心代码占比少。(面向对象编程方式不适用于调用一个函数)

    lambda表达式

  2. 本质是 接口实现类的对象
  3. 语法:(参数列表/只有一个参数时小括号可省略)-> {要放在该抽象方法内的核心代码}
    1. 左侧:指定了 Lambda 表达式需要的**参数列表 **
    2. 右侧:指定了 Lambda 体,是抽象方法的实现逻辑,也即Lambda 表达式要执行的功能
      Comparator<Integer> com = (x, y) -> Integer.compare(x, y); // 省略return
      Consumer<String> con = str -> sout(str);// 省略参数类型、小括号
      

方法引用

  • 方法引用,顾名思义可以理解为将java aip中已实现的方法传递到匿名函数内作为其方法体的实现
  • 方法引用可以看做是Lambda表达式深层次的表达。换句话说,方法引用本质是Lambda表达式,也就是函数式接口的一个实例,通过方法的名字来指向一个方法,可以认为是Lambda表达式的一个语法糖。、
  • 格式:使用操作符 “::” 将类(或对象) 与 方法名分隔开来。

如下三种主要使用情况:

  1. **对象::实例方法名 **
  2. 某个类的实例对象 **:: **调用本类内的实例方法
    Consumer<String> c = System.out :: println;
    c.accpet("abc");
    
  3. **类::静态方法名 **
  4. 直接通过类名引用出静态方法
    Comparator<Integer> com = Integer::compare;
    com.compare(11, 12);
    
  5. 类::实例方法名 — 默认按位置用参
  6. 接口方法的第一个参数是方法的调用者_(x, y) -> x.method(y)_,并且第二个参数是需要引用方法的参数(或无参数)时:className::methodName
    BiPredicate<String, String> bp = String::equals;
    bp.test("hi", "hello");
    

    构造器引用

  • **格式: ClassName::new **
  • 可以把构造器引用赋值给定义的方法,要求构造器参数列表要与接口中抽象方法的参数列表一致!且方法的返回值即为构造器对应类的对象。
  • image.png

    数组引用

    格式: type[] :: new
    image.png

    lambda数组排序

  1. Arrays.sort(要排序数组, comapre比较器)
  2. lambda实现接口:Integer.compare( a, b)or 其他comparable接口, 比较a b两个参数的大小
  3. 参数意义: a b分别表示数组中的两个原始数据, -> 之后为定制的排序方法, 若 a>b 则返回1 ; a<b return -1, a=b return 0
    Arrays.sort(array, (a,b) -> (Integer.compare( Math.abs(a),  Math.abs(b))));
    Stream.of(array).forEach(a ->  System.out.println(a));
    

    冒号 (::) 运算符,在 Java 中也称为方法引用运算符,用于通过类的帮助直接引用它来调用方法。它们的行为与 lambda 表达式完全相同。它与 lambda 表达式的唯一区别是,它通过名称直接引用方法,而不是向方法提供委托。
    句法:

    <类名> :: <方法名>