Files
Hui-s-notebook/Lambda表达式.md
2023-09-10 10:50:53 +08:00

4.6 KiB
Raw Blame History

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));

构建方法引用

  1. 指向静态方法的引用 Interger::parseInt
  2. 指向任意类型实例方法的方法引用 String::length
  3. 指向现有对象的实例方法的方法引用 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