3.2 在哪里以及如何使用Lambda
在函数式接口中使用Lambda表达式。
3.2.1 函数式接口
函数式接口是只定义一个抽象方法的接口,可以包含默认方法、静态方法。
测验3.2:函数式接口
下面哪些接口是函数式接口?
public interface Adder{
int add(int a, int b);
}
public interface SmartAdder extends Adder{
int add(double a, double b);
}
public interface Nothing{
}
只有Adder是函数式接口,其他都不是函数式接口,SmartAdder有两个抽象方法,Nothing没有抽象方法。
Lambda表达式可代替匿名类,以内联的形式为函数式接口的抽象方法提供实现,并把整个表达式作为函数式接口的实例。
public static void process(Runnable r) {
r.run();
}
// 匿名类
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println("hello, world 1");
}
};
// Lambda表达式
Runnable r2 = () -> System.out.println("hello, world 2");
// invoke
process(r1);
process(r2);
// Lambda表达式
process(() -> System.out.println("hello, world 3"));
3.2.2 函数描述符
函数描述符是Lambda表达式的签名,与赋值的函数式接口中的抽象方法签名一致。
java.time.function
中的函数式接口
泛型函数式接口 | 函数描述符 | 基本类型函数式接口 |
---|---|---|
Supplier<T> | () -> T | BooleanSupplier, IntSupplier, LongSupplier, DoubleSupplier |
Consumer<T> | T -> void | IntConsumer, LongConsumer, DoubleConsumer |
Predicate<T> | T -> boolean | IntPredicate, LongPredicate, DoublePredicate |
UnaryOperator<T> | T -> T | IntUnaryOperator, LongUnaryOperator, DoubleUnaryOperator |
Function<T, R> | T -> R | IntFunction<R>, LongFunction<R>, DoubleFunction<R> ToIntFunction<T>, ToLongFunction<T>, ToDoubleFunction<T> IntToLongFunction, IntToDoubleFunction, LongToIntFunction, LongToDoubleFunction, DoubleToIntFunction, DoubleToLongFunction |
BiConsumer<T, U> | (T, U) -> void | ObjIntConsumer<T>, ObLongConsumer<T>, ObjDoubleConsumer<T> |
BiPredicate<T, U> | (T, U) -> boolean | |
BinaryOperator<T> | (T, T) -> T | IntBinaryOperator, LongBinaryOperator, DoubleBinaryOperator |
BiFunction<T, U, R> | (T, U) -> R | ToIntBiFunction<T, U>, ToLongBiFunction<T, U>, ToDoubleBiFunction<T, U> |
函数式接口传递Lambda表达式,设计上通过自动映射为抽象方法的实现,避免语言变得更为复杂。(与函数类型相比)
测验3.3:在哪里可以使用Lambda?
以下哪些是使用Lambda表达式的有效方式?
-
execute(() -> {}); public void execute(Runnable r){ r.run(); }
√,函数描述符为
() -> void
-
public Callable<String> fetch() { return () -> "Tricky example ; -)"; }
√,函数描述符为
() -> String
-
Predicate<Apple> p=(Apple a)-> a.getWeight();
×,
(Apple a)-> a.getWeight();
函数描述符为Apple -> Integer
,与Predicate<Apple>的函数描述符Apple -> boolean
不相符合
JDK1.8中函数式接口加上标记注解@FunctionalInterface,表示该接口会被设计为函数式接口,如果同时定义多个抽象方法,编译器会提示报错“Multiple non-overriding abstract methods found in interface Xxx”。
另一个常见的标记注解是JDK1.5添加的@Override,用来表示方法被重写了。