lambda表达式

前提条件

使用Lambda表达式前提条件是:实现的接口是一个函数式接口

函数式接口

函数式接口就是在接口中只能有一个抽象方法。

Java 8 中还有一个注解@FunctionalInterface,表明接口是函数式接口。当然,不标注此注解,他也是函数式接口,注解只是起到编译检查的作用

java 8 提供了四大函数式接口:Consumer,Supplier,Function<T, R>,Predicate
在这里插入图片描述

语法

1
2
3
4
5
6
7
8
// 这个接口中的accept方法负责接受一个参数,不作返回
Consumer<String> consumer = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
consumer.accept("输出内容");

等同于

1
2
3
4
5
6
7
// Consumer<String> consumer = (s) -> {
// System.out.println(s);
// };
// 等同于下面的写法
Consumer<String> consumer = s -> System.out.println(s);

consumer.accept("输出内容");

这里可以看出,Lambda表达式充当了对象的身份。
在Lamdba中

  • -> 称作 Lambda操作符或箭头操作符
  • -> 左边的是方法的参数
    如果参数只有一个则可以省略小括号()
  • -> 右边的是接口中被重写的方法的方法体
    如果方法体中,只有一条语句,则可以省略大括号{ }
    如果方法体中,只有一条语句,且是返回语句,则可以省略return

方法引用

方法引用其实就是Lambda表达式特殊情况下的简写

使用条件

首先,使用方法引用前提是他能使用Lambda表达式,也就是函数式接口。第二点,实现接口的抽象方法的参数列表和返回值类型,必须于方法引用的方法的参数列表和返回值类型相同。(多数情况)

使用场景

三种情况:

  1. 对象::实例方法名
  2. 类::静态方法名
  3. 类::实例方法名

对于情况1,2,需要满足上述使用条件。对于情况3,需要满足参数中的第一个参数作为实例方法的调用者,而第二个参数是实例方法的参数。
举例:

  1. 对象::实例方法名
    1
    2
    3
    // 对象::实例方法名,等同于上述Lambda表达式例子
    Consumer<String> consumer = System.out::println;
    consumer.accept("输出内容");
  2. 类::静态方法名、
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Comparator<Integer> comparator1 = new Comparator<Integer>(){
    @Override
    public int compare(Integer o1, Integer o2) {
    // 类的静态方法
    return Integer.compare(o1,o2);
    }
    };
    //Lambda表达式写法
    Comparator<Integer> comparator2 = (o1,o2) -> Integer.compare(o1,o2);
    // 方法引用写法
    Comparator<Integer> comparator3 = Integer::compareTo;
  3. 类::实例方法名
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Comparator<String> comparator1 = new Comparator<String>(){
    @Override
    public int compare(String o1, String o2) {
    return o1.compareTo(o2);
    }
    };
    //Lambda表达式写法
    Comparator<String> comparator2 = (o1,o2) -> o1.compareTo(o2);
    // 方法引用,类的实例方法写法
    Comparator<String> comparator3 = String::compareTo;
    在Lambda表达式中,o1作为Lambda体中方法的调用者,而o2是方法的参数,即使他们的参数类型、返回值类型不同,仍然可以使用方法引用写法。

构造器引用和数组引用

构造器引用其实和方法引用差不多,将构造方法当成一个方法而已,而数组引用也只是将数组当成了一种类型。
构造器引用:

1
2
3
Function<String,MyClass> function1 = str -> new MyClass(str);

Function<String,MyClass> function2 = str -> MyClass::new;

数组引用:

1
2
3
Function<Integer,Integer[]> function3 = n -> new Integer[n];

Function<Integer,Integer[]> function4 = Integer[]::new;