Java Lambda 表达式笔记

1. Lambda 表达式是什么

Lambda 表达式是 Java 中一种简化写法,用来快速创建某个接口的实现对象。

它主要用于替代匿名内部类。

例如以前创建 Runnable:

复制代码
Runnable task = new Runnable() {
    @Override
    public void run() {
        System.out.println("执行任务");
    }
};

使用 Lambda 后:

复制代码
Runnable task = () -> {
    System.out.println("执行任务");
};

两者本质相同,都是在实现 Runnable 接口中的 run() 方法。


2. Lambda 的基本格式

复制代码
(参数列表) -> { 方法体 }

可以理解为:

复制代码
参数 -> 执行逻辑

例如:

复制代码
(a, b) -> {
    return a + b;
}

表示接收 a、b 两个参数,返回它们相加的结果。


3. Lambda 的常见写法

3.1 无参数、无返回值

复制代码
() -> {
    System.out.println("执行任务");
}

常用于 Runnable。

对应接口方法:

复制代码
void run();

3.2 一个参数、无返回值

复制代码
blog -> {
    System.out.println(blog.getTitle());
}

常用于 forEach()。

例如:

复制代码
records.forEach(blog -> {
    System.out.println(blog.getTitle());
});

这里的 blog 是集合中每次遍历到的一个元素。

等价于普通循环:

复制代码
for (Blog blog : records) {
    System.out.println(blog.getTitle());
}

3.3 多个参数、有返回值

复制代码
(a, b) -> a + b

例如排序:

复制代码
list.sort((a, b) -> Integer.compare(a, b));

这里 Lambda 接收两个元素 a、b,并返回比较结果。


3.4 一个参数、有返回值

复制代码
value -> Long.valueOf(value)

表示:

接收一个 value,把它转换为 Long 后返回。

完整写法:

复制代码
value -> {
    return Long.valueOf(value);
}

4. 单表达式为什么可以省略 return

下面这种写法:

复制代码
value -> Long.valueOf(value)

右侧只有一条表达式:

复制代码
Long.valueOf(value)

Java 会自动把这条表达式的结果作为返回值。

它等价于:

复制代码
value -> {
    return Long.valueOf(value);
}

规则:

复制代码
x -> x * 2

等价于:

复制代码
x -> {
    return x * 2;
}

但是,只要写了 {},就必须手动写 return:

复制代码
x -> {
    return x * 2;
}

下面是错误的:

复制代码
x -> {
    x * 2;
}

因为加上 {} 后,Java 不会自动返回最后一行结果。


5. Lambda 只能用于函数式接口

Lambda 只能用于函数式接口。

函数式接口指:

接口中只有一个抽象方法。

例如:

复制代码
public interface Runnable {
    void run();
}

只有一个抽象方法,因此可以使用 Lambda:

复制代码
Runnable task = () -> System.out.println("执行任务");

再例如:

复制代码
public interface Callable<V> {
    V call() throws Exception;
}

可以写:

复制代码
Callable<Integer> task = () -> 10 + 20;

因为 Callable<Integer> 的核心方法是:

复制代码
Integer call();

6. 常见函数式接口

接口 核心方法 参数 返回值 常见用途
Runnable run() 无 无 线程任务
Callable<V> call() 无 有 有返回值的线程任务
Consumer<T> accept(T t) 1个 无 forEach()
Function<T, R> apply(T t) 1个 有 map()
Predicate<T> test(T t) 1个 boolean filter()
Comparator<T> compare(T a, T b) 2个 int 排序

7. Lambda 的具体含义由外部接口决定

Lambda 本身不能脱离上下文单独存在。

例如:

复制代码
value -> Long.valueOf(value)

Java 要先看它被赋值给谁,才能确定:

  • value 是什么类型

  • 返回值是什么类型

  • 它是在实现哪个方法

例如:

复制代码
Function<String, Long> function = value -> Long.valueOf(value);

Java 会推断为:

复制代码
Long apply(String value)

等价于:

复制代码
Function<String, Long> function = new Function<String, Long>() {
    @Override
    public Long apply(String value) {
        return Long.valueOf(value);
    }
};

所以 Lambda 的参数类型、返回类型、对应方法,都是由目标函数式接口决定的。


8. forEach 中的 Lambda

例如:

复制代码
records.forEach(blog -> {
    Long userId = blog.getUserId();
    User user = userService.getById(userId);

    blog.setName(user.getNickName());
    blog.setIcon(user.getIcon());

    isBlogLiked(blog);
});

forEach() 需要的是:

复制代码
Consumer<T>

其核心方法是:

复制代码
void accept(T t);

因此:

复制代码
blog -> {
    ...
}

本质上是在实现:

复制代码
void accept(Blog blog)

因为 Consumer 返回值是 void,所以不需要 return。


9. map 中的 Lambda

例如:

复制代码
List<Long> ids = top5.stream()
        .map(value -> Long.valueOf(value))
        .collect(Collectors.toList());

执行过程:

复制代码
Set<String>
    ↓ stream()
Stream<String>
    ↓ map(value -> Long.valueOf(value))
Stream<Long>
    ↓ collect(Collectors.toList())
List<Long>

map() 的作用是:

将流中的每个元素转换成新的元素。

其中:

复制代码
value -> Long.valueOf(value)

表示:

复制代码
"101" -> 101L
"205" -> 205L
"309" -> 309L

map() 需要的是:

复制代码
Function<T, R>

核心方法:

复制代码
R apply(T t);

因此这里相当于:

复制代码
Function<String, Long>

即:

复制代码
Long apply(String value)

10. map 与 forEach 的区别

forEach:处理元素,不产生新结果

复制代码
list.forEach(value -> {
    System.out.println(value);
});

适合做:

  • 打印

  • 修改对象属性

  • 调用某个业务方法

  • 写日志

它不负责返回新集合。


map:转换元素,产生新结果

复制代码
list.stream()
        .map(value -> Long.valueOf(value))
        .collect(Collectors.toList());

适合做:

  • String 转 Long

  • User 转 UserDTO

  • Blog 转标题字符串

  • 数字转平方值

例如:

复制代码
user -> BeanUtil.copyProperties(user, UserDTO.class)

表示将每一个 User 转换为 UserDTO。


11. Lambda 与普通 for 循环的对应关系

Stream 写法:

复制代码
List<Long> ids = top5.stream()
        .map(value -> Long.valueOf(value))
        .collect(Collectors.toList());

普通循环写法:

复制代码
List<Long> ids = new ArrayList<>();

for (String value : top5) {
    Long id = Long.valueOf(value);
    ids.add(id);
}

对应关系:

Stream 写法 普通循环含义
stream() 开始遍历集合
map() 对每个元素做转换
value -> Long.valueOf(value) 当前元素转换为 Long
collect(toList()) 收集成 List

12. 方法引用

下面两种写法等价:

复制代码
.map(value -> Long.valueOf(value))

.map(Long::valueOf)

因为 Lambda 的逻辑只是:

复制代码
接收 value
调用 Long.valueOf(value)
返回结果

因此可以写成方法引用:

复制代码
类名::方法名

例如:

复制代码
.map(Long::valueOf)

初学阶段可以优先理解 Lambda 写法,熟悉后再使用方法引用。


13. 记忆总结

Lambda 的核心格式:

复制代码
(参数) -> { 逻辑 }

它本质上是:

对函数式接口中唯一抽象方法的简写实现。

常见形式:

复制代码
// 无参数、无返回值
() -> System.out.println("执行任务");

// 一个参数、无返回值
user -> System.out.println(user.getName());

// 一个参数、有返回值
value -> Long.valueOf(value);

// 两个参数、有返回值
(a, b) -> Integer.compare(a, b);

一句话总结:

Lambda 表达式不是独立的方法,而是根据外部需要的函数式接口,自动推断参数、返回值和对应方法的一种简写写法。

相关推荐
小程序设计10 小时前
本科毕设避坑|大数据 / 单片机物联网 / 网络工程 / PLC / 机械设计选题与落地心得
java·hive·hadoop·单片机
卓怡学长11 小时前
w206基于SpringBoot的社区团购小程序设计与实现
java·spring boot·spring·intellij-idea
Fruit_Caller11 小时前
static
开发语言·c++
IT枫斗者枫哥16 小时前
MyBatis一对多分页:LIMIT 20,为什么凑不齐20个订单?
java·数据库
代码方舟16 小时前
Java数据工程:利用天远全网运营商三要素优化线上实名认证合规体验
java·人工智能
BBmmo16 小时前
我的 Java 学习笔记 · 第 7 篇:泛型与通配符
java
独泪了无痕16 小时前
Hutool之RandomUtil:随机数生成的终极利器
java·后端
花开路口16 小时前
深入理解 Java/Kotlin 协变与逆变
java·kotlin
运行时异常16 小时前
【WMS 仓储系统集成 AI Agent 实战】第 7 讲:Vue3 前端工程化——Token 刷新锁、Markdown 渲染踩坑与权限体系
java
她的男孩16 小时前
开放接口限流从 20 改到 200 还是每分钟 20 次:拆完防重放+幂等+限流,我找到 5 个静默失效的坑
java·后端·架构