【Java 8】Lambda表达式


前言

作为匿名参数,Lambda 给我们带来了简洁、直观的函数表达,便于后期维护与二次开发。有关 Lambda 表达式的一切内容,将在本文呈现。


提示:以下是本篇文章正文内容,下面案例可供参考

一、Lambda介绍

可以理解为简洁地表示可传递的 匿名函数的一种方式:它没有名称,但它有参数列表 、函数主体、返回类型,可能还有一个可抛出的异常列表。

  • 匿名——不需要函数名称
  • 函数——和普通函数一样,Lambda有参数列表、函数主体、返回类型,还可能有可抛出的异常列表
  • 传递——Lambda表达式可作为参数传递给方法或存储在变量中
  • 简洁——无需像匿名类写很多模板代码

组成

  1. 参数列表
  2. 箭头:分隔参数列表与Lambda主体
  3. Lambda主体

基本语法

(parameters) -> expression
(parameters) -> { statements; }

二、Lambda使用场景

  1. 函数式接口:只定义一个抽象方法的接口。
    注意:接口可以拥有默认方法,哪怕有很多默认方法 ,只要接口只定义了一个抽象方法,它就仍然是一个函数式接口
  2. 函数描述符:函数式接口的抽象方法的签名与Lambda函数的签名一致,将这种抽象方法叫做函数描述符
    补充:方法的名字和參数列表成为方法的签名

三、环绕执行模式

环绕执行模式:初始化/准备代码 --> 任务 A/B --> 清理/结束代码

  1. 记得行为参数化
String result  = processFile((BufferedReader br) -> br.readLine() + br.readLine());
  1. 使用函数式接口来传递行为
@FunctionalInterface
public interface BufferedReaderProcessor {
    String process(BufferedReader b) throws IOException;
}
// 现在可以用这个接口作为新的 processFile 方法的参数
public static String processFile(BufferedReaderProcessor p) throws IOException {
    ...
}
  1. 执行一个行为
public static String processFile(BufferedReaderProcessor p) throws IOException {
    try (BufferedReader br = new BufferedReader(new FileReader("data.txt"))) {
        // 处理 BufferedReader 对象
        return p.process(br);
    }
}
  1. 传递Lambda
String oneLine = processFile((BufferedReader br) -> br.readLine());
String twoLine = processFile((BufferedReader br) -> br.readLine() + br.readLine());

四、原始类型特化

原始类型特化

Java类型

  • 引用类型(Byte、Integer、Object、List)
  • 原始类型(int、double、byte、char)

泛型(比如Consumer中的T)只能绑定引用类型,Java提供一套原始类型与引用类型转化的机制

  • 装箱:原始类型 --> 引用类型,本质上把原始类型包裹起来,并保存在堆里,需要更多内存,需要额外的内存搜索来获取被包装的原始值
  • 拆箱:引用类型 --> 原始类型

原始类型特化避免了上述的装箱操作

函数式接口函数描述符原始类型特化
PredicateT -> booleanIntPredicate, LongPredicate, DoublePredicate
CosumerT->voidIntConsumer, LongConsumer, DoubleConsumer
Function<T, R>T -> RIntFunction, IntToDoubleFunction, IntToLongFunction, LongFunction, LongToDoubleFunction, LongToIntFunction, DoubleFunction, ToIntFunction, ToDoubleFunction, ToLongFunction
Supplier() -> TBooleanSupplier, IntSupplier, LongSupplier, DoubleSupplier
UnaryOperatorT -> TIntUnaryOperator, LongUnaryOperator, DoubleUnaryOperator
BinaryOperator(T, T) -> TIntBinaryOperator, LongBinaryOperator, DoubleBinaryOperator
BiPredicate<L, R>(L, R) -> boolean
BiConsumer<T, U>(T, U) -> voidObjIntConsumer, ObjLongConsumer, ObjDoubleConsumer
BiFunction<T, U, R>(T, U) -> RToIntBiFunction<T, U>, ToLongBiFunction<T, U>, ToDoubleBiFunction<T, U>

五、方法引用

基本思想:如果一个Lambda代表的只是“直接调用这个方法”,最好用名称来调用,而不是去描述如何调用它。

Lambda等效的方法引用
(Apple a) -> a.getWeight()Apple::getWeight
()->Thread.currentThread().dumpStack()Thread.currentThread()::dumpStack
(str, i) -> str.substring(i)String::substring
(String s) -> System.out.println(s)System.out::println

分类

  1. 指向静态方法的方法引用:例如 Integer 的 parseInt 方法,Integer::parseInt
  2. 指向任意类型实例方法的方法引用:例如 String 的 length 方法,String::length
  3. 指向现有对象的实例方法的方法引用:假设有一个局部变量 expensiveTransaction 用于存放 Transaction 类型的对象,它支持实例方法 getValue,可以写 expensiveTransaction::getValue

构造函数引用

Supplier<Apple> c1 = Apple::new;
Apple a1 = c1.get();
// 构造函数签名是 Apple(Integer, weight)
Function<Integer, Apple> c2 = Apple::new;
Apple a2 = c2.apply(110);

总结

以上就是 Lambda 表达式的内容,本文介绍了Lambda表达式的组成、基本语法以及使用场景,又梳理了与 Lambda 表达式相关的环绕执行模式、原始类型特化以及方法引用。


@北京·海淀 2020.12.13

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值