Lambda 表达式怎么用

Lambda 表达式是 Java 8 引入的一项重要特性,它提供了一种简洁的方式 来表示匿名函数(即没有名字的函数) ,常用于实现函数式接口(只有一个抽象方法的接口)。在 Java 中,Lambda 表达式主要用于简化回调、事件处理、集合操作等场景。

🧩 一、基本语法

几种常见写法:

场景 Lambda 写法 说明
无参无返回 () -> System.out.println("Hello") 最简形式
一个参数 (x) -> x * 2x -> x * 2 单个参数可省略括号
多个参数 (x, y) -> x + y 必须加括号
多行语句 (x) -> { int r = x * 2; return r; } 需要大括号和 return
有返回值(单表达式) x -> x * 2 自动返回表达式结果

📌 二、使用前提:函数式接口

Lambda 只能用于函数式接口(Functional Interface),即:

  • 接口中有且仅有一个抽象方法
  • 可用 @FunctionalInterface 注解(非必须,但推荐)

常见内置函数式接口(都在 java.util.function 包中):

接口 方法 用途
Runnable void run() 无参无返回(如线程任务)
Consumer<T> void accept(T t) 消费一个参数,无返回
Supplier<T> T get() 无参,有返回
Function<T, R> R apply(T t) 有参有返回
Predicate<T> boolean test(T t) 判断条件(返回 boolean)

✅ 这些接口你不需要自己写,直接用!


🧪 三、实际例子

1. 线程启动(使用 Runnable

复制代码
// 传统方式
new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("老写法");
    }
}).start();

// Lambda 方式
new Thread(() -> System.out.println("Lambda 启动线程!")).start();

2. 集合遍历(使用 Consumer

复制代码
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");

// 传统 for-each
for (String name : names) {
    System.out.println(name);
}

// 使用 Lambda + forEach
names.forEach(name -> System.out.println(name));

// 更简:方法引用
names.forEach(System.out::println);

3. 过滤数据(使用 Predicate

复制代码
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);

// 找出偶数
List<Integer> evens = numbers.stream()
    .filter(n -> n % 2 == 0)   // Predicate<Integer>
    .collect(Collectors.toList());

System.out.println(evens); // [2, 4, 6]

4. 自定义回调

复制代码
@FunctionalInterface
interface Callback {
    void call(String message);
}

public static void doTask(Callback cb) {
    System.out.println("执行任务中...");
    cb.call("任务完成!");
}

// 调用
doTask(msg -> System.out.println("收到: " + msg));

5. 返回值(使用 Function

复制代码
Function<String, Integer> strToInt = s -> Integer.parseInt(s);
int num = strToInt.apply("123");
System.out.println(num + 1); // 124

⚠️ 四、注意事项

  1. Lambda 不能单独存在,必须赋值给一个函数式接口类型。

    复制代码
    // ❌ 错误:不能这样写
    x -> x + 1;
    
    // ✅ 正确
    Function<Integer, Integer> f = x -> x + 1;
  2. 变量捕获(闭包)

    • Lambda 可以访问外部局部变量,但该变量必须是 effectively final(实际上不可变)

      int factor = 10; // 实际上 final(没被修改)
      Function<Integer, Integer> multiply = x -> x * factor;

  3. 不能修改外部局部变量:

    复制代码
    int count = 0;
    Runnable r = () -> count++; // ❌ 编译错误!

🔁 五、Lambda vs 匿名内部类

特性 匿名内部类 Lambda
语法 冗长 简洁
性能 每次创建新类 JVM 优化(可能复用)
适用范围 任意接口/抽象类 仅函数式接口
this 指向 匿名类实例 外部类实例

✅ 总结

Lambda 表达式让你用更少的代码做更多的事,尤其适合:

  • 回调函数
  • 集合流式操作(stream().map().filter().forEach()
  • 事件监听
  • 并发任务(如 ExecutorService.submit(() -> {...})

💡 记住口诀:"左边参数,右边逻辑,中间箭头"(params) -> { body }

复制代码
(参数列表) -> { 函数体 }
相关推荐
_F_y7 小时前
C++重点知识总结
java·jvm·c++
打工的小王7 小时前
Spring Boot(三)Spring Boot整合SpringMVC
java·spring boot·后端
毕设源码-赖学姐7 小时前
【开题答辩全过程】以 高校体育场馆管理系统为例,包含答辩的问题和答案
java·spring boot
我真会写代码7 小时前
SSM(指南一)---Maven项目管理从入门到精通|高质量实操指南
java·spring·tomcat·maven·ssm
vx_Biye_Design7 小时前
【关注可免费领取源码】房屋出租系统的设计与实现--毕设附源码40805
java·spring boot·spring·spring cloud·servlet·eclipse·课程设计
java干货8 小时前
为什么 “File 10“ 排在 “File 2“ 前面?解决文件名排序的终极算法:自然排序
开发语言·python·算法
_F_y8 小时前
C语言重点知识总结(含KMP详细讲解)
c语言·开发语言
DN金猿8 小时前
接口路径正确,请求接口却提示404
java·tomcat
毕设源码-郭学长8 小时前
【开题答辩全过程】以 基于python的二手房数据分析与可视化为例,包含答辩的问题和答案
开发语言·python·数据分析
无小道8 小时前
Qt——常用控件
开发语言·qt