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 }

复制代码
(参数列表) -> { 函数体 }
相关推荐
梓䈑2 小时前
【C++】C++11(右值引用和移动语义、可变参数模板 和 包装器)
java·开发语言·c++
深海蓝山2 小时前
WebSocket(java版)服务示例
java·websocket·网络协议
Howe~zZ2 小时前
mybatis 报错解决方案ORA-01795: maximum number of expressions in a list is 1000
java·服务器·前端
LiamTuc2 小时前
Java 抽象类详解
java·开发语言
计算机学姐2 小时前
基于Python的高校后勤报修系统【2026最新】
开发语言·vue.js·后端·python·mysql·django·flask
GSDjisidi2 小时前
日本IT行业|一些it資格证书分享解析,一篇通读
开发语言·面试·职场和发展
南山乐只2 小时前
Spring Boot 2.x => 3.x 升级指南
java·spring boot·后端
任子菲阳2 小时前
学Java第五十五天——多线程&JUC
java·开发语言
yaoxin5211232 小时前
265. Java 集合 - LinkedList vs ArrayList 插入性能实战对比分析
java·开发语言