一、前言

在 Java 8 之前,我们写代码时常常被冗长的匿名内部类困扰 —— 明明核心逻辑只有一两行,却要写一堆模板代码。Lambda 表达式的出现,彻底改变了这一现状,它让 Java 拥有了函数式编程的简洁,也让我们的代码更聚焦业务逻辑本身。

本文将从实际痛点出发,带你从零认识 Lambda 表达式,手把手写出第一个 Lambda 程序。

二、为什么需要 Lambda?

在 Lambda 出现前,我们处理线程创建、集合排序等场景时,必须使用匿名内部类,代码冗余且可读性差。先看两个典型场景的对比:

场景 1:创建线程(Runnable 接口)

传统匿名内部类写法 :

public class ThreadDemo {
    public static void main(String[] args) {
        // 创建线程:核心逻辑只有打印一句话,却写了6行模板代码
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("传统方式创建线程:Hello World!");
            }
        }).start();
    }
}

Lambda 写法 :

public class ThreadLambdaDemo {
    public static void main(String[] args) {
        // 核心逻辑直接暴露,代码简化到1行
        new Thread(() -> System.out.println("Lambda创建线程:Hello World!")).start();
    }
}

场景 2:集合排序(Comparator 接口)

传统匿名内部类写法 :

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class SortDemo {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("Java");
        list.add("Lambda");
        list.add("Stream");

        // 按字符串长度排序:核心逻辑是compare方法,却嵌套了多层代码
        Collections.sort(list, new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                return s1.length() - s2.length();
            }
        });

        System.out.println(list); // 输出:[Java, Stream, Lambda]
    }
}

Lambda 写法 :

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class SortLambdaDemo {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("Java");
        list.add("Lambda");
        list.add("Stream");

        // 直接写核心比较逻辑,代码量减少一半
        Collections.sort(list, (s1, s2) -> s1.length() - s2.length());

        System.out.println(list); // 输出:[Java, Stream, Lambda]
    }
}

对比总结

从上面的例子能明显看出:Lambda 表达式剔除了匿名内部类的模板代码,只保留核心的业务逻辑,让代码更简洁、可读性更高。

三、本质:简化函数式接口的实现

要理解 Lambda,必须先掌握 “函数式接口” 这个核心概念 ——Lambda 表达式本质上就是函数式接口的简化写法。

1、函数式接口的定义

函数式接口(Functional Interface)是指:只有一个抽象方法的接口(可以包含默认方法、静态方法,不影响)。

Java 为函数式接口提供了专门的注解@FunctionalInterface,作用有两个:

  • 编译器校验:如果接口不符合 “只有一个抽象方法” 的规则,会直接编译报错;

  • 可读性提升:一眼就能识别这是函数式接口,方便配合 Lambda 使用。

示例:自定义一个简单的函数式接口

// 注解可选,但建议加上,增强可读性和校验
@FunctionalInterface
public interface MyFunctionalInterface {
    // 唯一的抽象方法
    void doSomething(String msg);

    // 允许有默认方法
    default void defaultMethod() {
        System.out.println("这是默认方法");
    }

    // 允许有静态方法
    static void staticMethod() {
        System.out.println("这是静态方法");
    }
}

2、Lambda 与函数式接口的关系

Lambda 表达式只能用于函数式接口的实现 —— 因为 Lambda 没有指定实现哪个方法,只能匹配 “只有一个抽象方法” 的接口。

比如前面的Runnable接口,源码就是典型的函数式接口:

@FunctionalInterface
public interface Runnable {
    void run();
}

Lambda表达式() -> System.out.println("Hello"),本质就是实现了Runnable的run()方法。

四、基本语法

Lambda 的核心语法格式非常简单,可拆解为三部分:

(参数列表) -> { 代码块 }

组成部分

说明

(参数列表)

对应函数式接口抽象方法的参数:

1. 参数类型可省略(编译器自动推断);

2. 只有一个参数时,括号()可省略;

3. 无参数时,保留空括号();

->

箭头操作符:分隔参数和代码块,固定写法。

{代码块}

对应函数式接口抽象方法的实现逻辑:

1. 代码块只有一行时,大括号{}可省略;

2. 一行代码如果是返回语句,return可省略;

语法示例(覆盖常见场景)

下面以自定义的函数式接口为例,展示不同语法写法:

// 定义函数式接口:计算两个整数的结果
@FunctionalInterface
interface Calculator {
    int calculate(int a, int b);
}
public class LambdaSyntaxDemo {
    public static void main(String[] args) {
        // 1. 完整写法:带参数类型、大括号、return
        Calculator add1 = (int a, int b) -> {
            return a + b;
        };
        System.out.println(add1.calculate(1, 2)); // 输出:3

        // 2. 简化:省略参数类型(编译器自动推断)
        Calculator add2 = (a, b) -> {
            return a + b;
        };
        System.out.println(add2.calculate(3, 4)); // 输出:7

        // 3. 进一步简化:一行代码省略大括号和return
        Calculator add3 = (a, b) -> a + b;
        System.out.println(add3.calculate(5, 6)); // 输出:11

        // 补充:无参数场景(如Runnable)
        Runnable run = () -> System.out.println("无参数Lambda");
        // 补充:单个参数场景(省略括号)
        Calculator square = a -> a * a;
        System.out.println(square.calculate(7, 0)); // 输出:49
    }
}

五、第一个完整的Lambda程序

接下来我们写一个可直接运行的完整示例,涵盖 Lambda 的核心用法 —— 遍历集合:

import java.util.ArrayList;
import java.util.List;
public class FirstLambdaProgram {
    public static void main(String[] args) {
        // 1. 准备一个字符串集合
        List<String> fruitList = new ArrayList<>();
        fruitList.add("苹果");
        fruitList.add("香蕉");
        fruitList.add("橙子");

        // 2. 传统for循环遍历(对比)
        System.out.println("传统for循环遍历:");
        for (String fruit : fruitList) {
            System.out.println(fruit);
        }

        // 3. Lambda表达式遍历(forEach方法接收Consumer函数式接口)
        System.out.println("\nLambda表达式遍历:");
        fruitList.forEach(fruit -> System.out.println("水果:" + fruit));

        // 4. 更简化的Lambda(一行代码)
        System.out.println("\n简化Lambda遍历:");
        fruitList.forEach(System.out::println); // 方法引用,后续文章详解
    }
}

运行结果 :

传统for循环遍历:
苹果
香蕉
橙子

Lambda表达式遍历:
水果:苹果
水果:香蕉
水果:橙子

简化Lambda遍历:
苹果
香蕉
橙子

六、总结

  1. Lambda 表达式是 Java 8 引入的函数式编程特性,核心作用是简化 函数式接口 (仅一个抽象方法的接口)的实现,替代冗长的匿名内部类。

  2. Lambda 的基础语法为(参数列表) -> {代码块},支持参数类型省略、单参数括号省略、单行代码大括号 /return 省略等简化写法。

  3. Lambda 的使用场景集中在线程创建、集合排序 / 遍历、Stream 流操作等,核心优势是让代码聚焦业务逻辑,提升可读性和简洁性。

下一篇文章,我们将深入讲解 Lambda 的 “基石”—— 函数式接口,带你掌握 Java 内置的核心函数式接口,让 Lambda 的使用更灵活!

更多推荐