Lambda

Lambda 表达式是 Java 8 引入的重要特性,本质是匿名函数(没有名称的函数),用于简化函数式接口的实现,使代码更简洁、紧凑。它特别适合处理集合的遍历、过滤、映射等操作,是函数式编程在 Java 中的核心体现。

一、Lambda 表达式的基本概念

1. 函数式接口(前提)

Lambda 表达式只能用于函数式接口 ------ 即只包含一个抽象方法的接口 (可包含默认方法或静态方法)。Java 内置了大量函数式接口(如 RunnableComparatorConsumer 等),也可自定义。

复制代码
// 自定义函数式接口(只有一个抽象方法)
@FunctionalInterface // 注解可校验是否为函数式接口
interface MathOperation {
    int operate(int a, int b);
}
2. Lambda 语法结构

Lambda 表达式的语法格式:

复制代码
(参数列表) -> { 方法体 }
  • 参数列表:与函数式接口中抽象方法的参数一致,可省略参数类型(编译器自动推断)。
  • ->:箭头符号,分隔参数列表和方法体。
  • 方法体 :实现抽象方法的逻辑,若只有一行代码可省略 {}return(若有返回值)。

二、Lambda 表达式的简化写法

根据场景不同,Lambda 可逐步简化,以下是常见形式:

1. 完整写法(带参数类型和方法体)
复制代码
MathOperation addition = (int a, int b) -> {
    return a + b;
};
2. 省略参数类型(编译器自动推断)
复制代码
MathOperation subtraction = (a, b) -> {
    return a - b;
};
3. 方法体只有一行代码(省略 {}return
复制代码
MathOperation multiplication = (a, b) -> a * b; // 自动返回结果
4. 无参数的情况
复制代码
// Runnable 接口(无参数,无返回值)
Runnable runnable = () -> System.out.println("Lambda 运行中");
5. 单个参数(可省略参数的括号)
复制代码
// Consumer 接口(单个参数,无返回值)
Consumer<String> consumer = s -> System.out.println(s);

三、Lambda 表达式的核心应用场景

1. 替代匿名内部类

传统匿名内部类代码冗长,Lambda 可大幅简化:

传统方式(匿名内部类)

复制代码
// 线程创建
new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("线程运行");
    }
}).start();

Lambda 方式

复制代码
new Thread(() -> System.out.println("线程运行")).start();
2. 集合遍历与操作

结合 Java 8 新增的 Stream API,Lambda 可简洁处理集合的遍历、过滤、排序等:

示例 1:遍历集合

复制代码
List<String> list = Arrays.asList("apple", "banana", "cherry");

// 传统 for 循环
for (String s : list) {
    System.out.println(s);
}

// Lambda + forEach
list.forEach(s -> System.out.println(s));
// 更简化(方法引用)
list.forEach(System.out::println);

示例 2:集合排序

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

// 传统方式(匿名内部类)
Collections.sort(numbers, new Comparator<Integer>() {
    @Override
    public int compare(Integer o1, Integer o2) {
        return o1 - o2; // 升序
    }
});

// Lambda 方式
Collections.sort(numbers, (a, b) -> a - b); // 升序
// 更简化(方法引用)
numbers.sort(Integer::compareTo);

示例 3:过滤与映射(Stream API)

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

// 过滤偶数并计算平方和
int sum = numbers.stream()
    .filter(n -> n % 2 == 0) // 过滤偶数
    .map(n -> n * n) // 计算平方
    .reduce(0, Integer::sum); // 求和

System.out.println(sum); // 输出:2² + 4² + 6² = 4 + 16 + 36 = 56
3. 自定义函数式接口

通过自定义函数式接口,可将 Lambda 作为参数传递,实现灵活的业务逻辑:

复制代码
// 自定义函数式接口(处理字符串)
@FunctionalInterface
interface StringProcessor {
    String process(String s);
}

// 工具方法:接收 Lambda 作为参数
public static String handleString(String s, StringProcessor processor) {
    return processor.process(s);
}

// 使用
public static void main(String[] args) {
    // 转换为大写
    String upper = handleString("hello", s -> s.toUpperCase());
    System.out.println(upper); // HELLO

    // 反转字符串
    String reversed = handleString("hello", s -> new StringBuilder(s).reverse().toString());
    System.out.println(reversed); // olleh
}

四、Lambda 表达式的底层原理

Lambda 表达式在编译后不会生成匿名内部类 ,而是通过 invokedynamic 指令动态生成一个函数式接口的实现类,本质是语法糖,但比匿名内部类更高效(减少类文件生成)。

例如,以下 Lambda 表达式:

复制代码
Runnable r = () -> System.out.println("Lambda");

编译后会生成一个类似以下的实现类(由 JVM 动态创建,不在字节码中显式存在):

复制代码
class Lambda$1 implements Runnable {
    @Override
    public void run() {
        System.out.println("Lambda");
    }
}

五、Lambda 表达式的注意事项

  1. 访问外部变量 :Lambda 可访问外部的 final事实上 final (即未声明为 final 但未被修改)的变量。

    复制代码
    int num = 10; // 事实上 final(未被修改)
    Runnable r = () -> System.out.println(num); // 合法
    // num = 20; // 若修改,编译报错
  2. this 关键字 :Lambda 中的 this 指向包围它的外部类对象 ,而匿名内部类的 this 指向自身实例。

  3. 方法引用(进一步简化) :若 Lambda 方法体只是调用一个已存在的方法,可使用方法引用:: 语法)进一步简化:

    复制代码
    // Lambda 方式
    list.forEach(s -> System.out.println(s));
    // 方法引用方式(等价)
    list.forEach(System.out::println);

    常见方法引用类型:

    • 静态方法引用:ClassName::staticMethod(如 Integer::parseInt)。
    • 实例方法引用:instance::method(如 str::length)。
    • 类的实例方法引用:ClassName::method(如 String::equals)。
    • 构造方法引用:ClassName::new(如 ArrayList::new)。

总结

Lambda 表达式的核心价值是简化代码支持函数式编程,尤其在集合操作和事件处理中优势明显。其使用前提是函数式接口,语法简洁灵活,可根据场景逐步简化。

掌握 Lambda 表达式需要理解:

  • 函数式接口是基础。
  • 语法格式:(参数) -> 方法体
  • 常见应用:替代匿名内部类、集合遍历与 Stream 操作。
  • 方法引用是 Lambda 的进一步简化。

Lambda 表达式是 Java 现代化的重要一步,与 Stream API、Optional 等特性结合,能显著提升代码的可读性和开发效率。

相关推荐
龙茶清欢3 小时前
5、urbane-commerce 微服务统一依赖版本管理规范
java·运维·微服务
海琴烟Sunshine5 小时前
Leetcode 26. 删除有序数组中的重复项
java·算法·leetcode
RoboWizard5 小时前
移动固态硬盘连接手机无法读取是什么原因?
java·spring·智能手机·电脑·金士顿
笨蛋不要掉眼泪5 小时前
SpringBoot项目Excel成绩录入功能详解:从文件上传到数据入库的全流程解析
java·vue.js·spring boot·后端·spring·excel
wshzrf6 小时前
【Java系列课程·Java学前须知】第3课 JDK,JVM,JRE的区别和优缺
java·开发语言·jvm
铅笔侠_小龙虾6 小时前
JVM 深入研究 -- 详解class 文件
java·开发语言·jvm
聪明的笨猪猪6 小时前
面试清单:JVM类加载与虚拟机执行核心问题
java·经验分享·笔记·面试
韶光流年都束之高阁6 小时前
Java中的TCP与UDP
java·tcp/ip·udp
练习时长一年6 小时前
ApplicationContext接口实现(二)
java·开发语言