Lambda表达式

Lambda

需要解决的问题

Lambda表达式其实就是一个匿名函数。
有这样一种场景,需要构造一个TreeSet,而TreeSet的构造方法需要一个Comparator接口的实现,所以需要这样构造:

@Test
public void test1() {
    Comparator<Integer> comparator = new Comparator<Integer>() {
        @Override
        public int compare(Integer o1, Integer o2) {
            return o1 - o2;
        }
    };
    TreeSet<Integer> set = new TreeSet<>(comparator);
}

以上代码对于Comparator的构造,有用的部分只有o1 - o2,但是由于java语法的约束,需要更多无关的代码。
Lambda表达式则是解决这个问题,通过Lambda表达式,上述代码可以写做:

@Test
public void test2() {
    Comparator<Integer> comparator = (o1, o2) -> o1 - o2;
    TreeSet<Integer> set = new TreeSet<>(comparator);
}

由此Lambda表达式可以极大精简我们的代码。

案例需求:
需要对两个数进行加减乘除等运算,怎么实现?
传统方式:

public static void main(String[] args) {
    add(2,1);
    minus(2,1);
    multiply(2,1);
    divide(2,1);
  }
  
  static int add(int left, int right) {
    return left + right;
  }

  static int minus(int left, int right) {
    return left - right;
  }
  static int multiply(int left, int right) {
    return left * right;
  }

  static int divide(int left, int right) {
    return left / right;
  }

函数式编程:

public static void main(String[] args) {
    calc(2, 1, (left, right) -> left + right);
    calc(2, 1, (left, right) -> left - right);
    calc(2, 1, (left, right) -> left * right);
    calc(2, 1, (left, right) -> left / right);
  }

  static int calc(int left, int right, Calculate calculate) {
    return calculate.applyAsInt(left, right);
  }

  @FunctionalInterface
  interface Calculate {
    int applyAsInt(int left, int right);
  }

使用Lambda表达式的条件

Lambda表达式只能作为函数式接口的表达式

什么是函数式接口

  • 像Runnable和Comparator这样只有一个抽象方法的接口,称为函数式接口。 也可以在接口上加上@FunctionalInterface注解,如果编译通过,则该接口就是函数式接口。
  • lambda表达式就是对函数式接口中那个唯一的抽象方法的实现

函数式接口大部分定义在 java.util.function包中, 且用@FunctionalInterface注解

四大函数式接口

接口名 参数类型 返回值类型 方法 类型
Predicate T boolean boolean test(T obj) 断言接口
Consumer T void void accept(T obj) 消费接口
Function<T,R> T R R apply(T obj) 函数接口
Supplier none T T get() 供给接口

方法引用

如果Lambda中的内容已经有方法实现了,可以使用“方法引用”。
方法引用是Lambda表达式的另一种表现形式。
采用方法引用时,被引用的方法的入参类型和返回值必须和Lambda表达式一样。

  1. 对象::实例方法名
        PrintStream printStream = System.out;
        Consumer consumer1 = i -> System.out.println(i);
        Consumer consumer2 = printStream::println;
  1. 类::静态方法名
        Comparator<Integer> comparator1 = (i, j) -> Integer.compare(i, j);
        Comparator<Integer> comparator2 = Integer::compare;
  1. 类::实例方法名
    这个方法限制比较多,也比较少用。
  • lambda必须两个入参,且调用的方法只能有一个入参
  • 第一个参数作为实例方法的调用者,第二个参数作为实例方法的入参
        BiFunction<String, String, Boolean> c = (i, j) -> i.equals(j);
        BiFunction<String, String, Boolean> c1 = String::equals;

构造方法引用

与函数式接口相结合,自动与函数式接口中方法兼容。
可以把构造器引用赋值给定义的方法,与构造器参数列表要与接口中抽象方法的参数列表一直

Function<Integer,MyClass> fun=(n)->new MyClass(n);
Function<Integer,MyClass> fun=MyClass::new;

数组引用

type[]::new


posted @ 2020-08-24 16:18  刃牙  阅读(246)  评论(0编辑  收藏  举报