简介
Lambda可以理解为简洁的表示可传递的匿名函数,包括:参数列表、函数主体、返回类型、抛出的异常列表(可以不存在)。
函数式接口:定义一个抽象方法的接口(接口可以拥有默认方法:default)。
函数式接口有什么用?
Lambda可以以内联的形式为函数式接口的抽象方法提供实现。虽然内部类也可以实现,但lambda表达式更加简洁。当然内部类也存在它的优势,它可以为接口实现多个抽象方法。
Comparator<Apple> byWeight =
(Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight());
参数列表:包括a1、a2,这里参数为显式类型(Apple类);也可以没有显示类型,java编译器会根据上下文配合Lambda表达式的函数式接口。
箭头:-> 将参数列表和函数主体分开
函数主体:要完成的功能;表达式作为返回值
1、(String s)->return s;
2、(String s)->{"Hello world"};
3、(String s)->"Hello world"
表达式1:return是一个控制流语句,需要用{}
表达式2:“Hello world”是一个表达式,不是语句,不需要花括号。
表达式3:正确
java.util.function包中的三个常用函数式接口:
1、Predicate
@FunctionalInterfacepublic interface Predicate<T>{
boolean test(T t);
}
2、Consumer
@FunctionalInterface
public interface Consumer<T>{
void accept(T t);
}
3、Function
@FunctionalInterface
public interface Function<T, R>{
R apply(T t);
}
注意:
1、由于Lambda只能捕捉给它的局部变量一次,局部变量必须显示申明为final或事实上为final。(局部变量保存在栈)
2、Lambda的主体为语句表达式时,它可以和返回为void的函数描述符兼容。add方法实际返回boolean类型,Consumer的accept方法返回为void类型,可以兼容而不报错。
Consumer<String> l = s -> list.add(s);
方法引用:这里选用最常见的sort方法,假设提供了一个Apple类,存在weight(重量)这个属性,类型为Integer(方便使用compareTo进行说明),现在我们要求按重量排序。
两行代码的实现相同,第一行
apples.sort((Apple a1, Apple a2)-> a1.getWeight().compareTo(a2.getWeight()));
apples.sort(Comparator.comparing(Apple::getWeight));
复合lambda表达式:将多个简单的lambda复合成复杂的表达式。
1、比较器复合
// 逆序apples.sort(Comparator.comparing(Apple::getWeight).reversed());// 比较器链apples.sort(Comparator.comparing(Apple::getWeight).thenComparing(Apple::getColor()));
2、微词复合:negate(非)、and和or。
3、函数复合
Function<Integer, Integer> f = x -> x+1;
Function<Integer, Integer> g = x -> x*2;
Function<Integer, Integer> h1 = f.andThen(g); //可以看作数学函数:h1 = f(g(x))
Function<Integer, Integer> h2 = f.compose(g); //h1 = g(f(x))
int result1 = h1.apply(1); //result1 = 4
int result2 = h2.apply(1); //result2 = 3