4.6 KiB
4.6 KiB
Lambda管中窥豹
- 匿名
- 函数
- 传递
- 简洁
更简洁的自定义一个Comparator对象
Comparator<Apple> byWeight=
(Apple a1, Apple a2)-> a1.getWeight().compareTo(a2.getWeight());
组成部分:
- 参数列表 采用了方法的参数
- 箭头 ->把参数列表和主体分隔开
- Lambda主体 表达式为Lambda的返回值
基本语法
(parameters)-> { statements; }
在哪里使用Lambda
函数式接口
只定义一个抽象方法的接口 (接口只定义了一个抽象方法,就仍然是一个函数式接口)
Lambda允许直接以内联的形式为函数式接口的抽象方法提供实现
函数描述符
函数式接口的抽象方法的签名基本上就是Lambda表达式的签名, Runnable接口可以看作一个什么也不接受也不返回的函数签名, 只有一个run的抽象方法,什么也不接受也不返回
环绕执行模式
// 行为参数化
String result=processFile((BufferedReader br)->
br.readLine()+br.readLine());
// 使用函数式接口来传递行为
@FunctionalInterface
public interface BufferedReaderProcessor {
String process(BufferedReader b) throws IOException;
}
public static String processFile(BufferedReaderProcessor p) throws
IOException {
…
}
// 执行一个行为,写一个实现方法
// 传递Lambda
String oneLine = processFile((BufferedReader br)-> br.readLine());
String twoLines = processFile((BufferedReader br)-> br.readLine()+br.readLine());
使用函数式接口
java.util.function
Predicate
test方法,接受泛型T对象,返回一个boolean
Consumer
accept方法,接受泛型T对象,没有返回,for-Each
Function
apply方法,接受泛型T对象,返回泛型R对象,map
类型检查、类型推断以及限制
类型检查
从使用Lambda的上下文推断出来的
同样的lambda,不同的函数式接口
同一个Lambda表达式可以与不同的函数式接口联系起来
Callable<Integer> c=()-> 42;
PrivilegedAction<Integer> p=()-> 42;
// Predicate返回了一个boolean
Predicate<String> p=s-> list.add(s);
// Consumer返回了一个void
Consumer<String> b=s-> list.add(s);
ToIntBiFunction<Apple, Apple> c2=
(Apple a1, Apple a2)-> a1.getWeight().compareTo(a2.getWeight());
BiFunction<Apple, Apple, Integer> c3=
(Apple a1, Apple a2)-> a1.getWeight().compareTo(a2.getWeight());
特殊的void兼容规则
如果一个Lambda主体为一个语句表达式,它就和一个返回void的函数描述符兼容
// Predicate返回了一个boolean
Predicate<String> p=s-> list.add(s);
// Consumer返回了一个void
Consumer<String> b=s-> list.add(s);
类型推断
Java编译器从上下文推断出用什么函数式接口配合Lambda表达式
// 无类型推断
Comparator<Apple, Apple> c=
(Apple a1, Apple a2)-> a1.getWeight().compareTo(a2.getWeight());
// 有类型推断
Comparator<Apple, Apple> c2=
(a1, a2)-> a1.getWeight().compareTo(a2.getWeight());
使用局部变量
Lambda可以没有限制的捕获实例变量和静态变量,但是局部变量必须显式声明为final或事实final
int portNumber=1337;
Runnable r=()-> System.out.println(portNumber);
// 如果对protNumber赋值,代码无法编译
protNumber = 31313;
实例变量存储在堆中,局部变量存储在栈中,使用Lambda的线程实在访问局部变量的副本,而不是原始变量
方法引用
inventory.sort(comparing(Apple::getWeight));
构建方法引用
- 指向静态方法的引用 Interger::parseInt
- 指向任意类型实例方法的方法引用 String::length
- 指向现有对象的实例方法的方法引用 expensive-Transaction::getValue
构造函数引用
ClassName::new
Function<Integer, Apple> c2 = Apple::new
复合Lambda表达式
比较器复合(Comparato)
Comparator<Apple> c=Comparator.comparing(Apple::getWeight);
// 逆序
inventory.sort(Apple::getWeight).reversed();
// 比较器链
inventory.sort(Apple::getWeight).reversed().thenComparing(Apple::getCounrty);
谓词复合(Predicate)
// negate返回非
Predicate<Apple> notRedApple = redApple.negate();
// and和
Predicate<Apple> notRedHeavyApple = redApple.and(a.getWeight() > 150);
// or或
Predicate<Apple> redAndHeavyAppleOrGreen = redApple.and(a.getWeight() > 150).or(a -> "green".equals(a.getColor()));
函数复合(Funciton)
andThen
g(f(x)),f.andThen(g),先作用f,后作用g
compose
f(g(x)),f.andThen(g),先作用g,后作用f