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

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


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 接收两个元素 ab,并返回比较结果。


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

适合做:

  • StringLong

  • UserUserDTO

  • 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 表达式不是独立的方法,而是根据外部需要的函数式接口,自动推断参数、返回值和对应方法的一种简写写法。

相关推荐
会周易的程序员1 小时前
使用 pybind11 封装 C++ 日志库 microLog 为 Python 模块
java·c++·python·物联网·架构·日志·aiot
zhixingheyi_tian1 小时前
一份GC日志的解读
java·开发语言
czhaii1 小时前
串口1中断收发-C语言-MODBUS协议
c语言·开发语言
ywl4708120871 小时前
ArrayList和LinkedList内部的实现原理和区别
java·java基础
沉静的小伙1 小时前
Spring事务
java·数据库·spring
apihz2 小时前
随机驾考题目(C 照科一 / 科四 2000+ 题)免费API调用教程
android·java·c语言·开发语言·网络协议·tcp/ip
AIGS0012 小时前
企业AI落地:Agent OS 治理框架实践
java·大数据·人工智能·机器学习·人工智能ai大模型应用
matlab代码2 小时前
基于matlab人脸疲劳驾驶检测系统(可使用其它人脸视频)【源码39期】
开发语言·matlab·人脸疲劳检测
-西门吹雪3 小时前
现代C++ 并发编程-学习指南
java·jvm·c++