一、前言
在 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. 一行代码如果是返回语句, |
语法示例(覆盖常见场景)
下面以自定义的函数式接口为例,展示不同语法写法:
// 定义函数式接口:计算两个整数的结果 @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遍历: 苹果 香蕉 橙子六、总结
Lambda 表达式是 Java 8 引入的函数式编程特性,核心作用是简化 函数式接口 (仅一个抽象方法的接口)的实现,替代冗长的匿名内部类。
Lambda 的基础语法为
(参数列表) -> {代码块},支持参数类型省略、单参数括号省略、单行代码大括号 /return 省略等简化写法。Lambda 的使用场景集中在线程创建、集合排序 / 遍历、Stream 流操作等,核心优势是让代码聚焦业务逻辑,提升可读性和简洁性。
下一篇文章,我们将深入讲解 Lambda 的 “基石”—— 函数式接口,带你掌握 Java 内置的核心函数式接口,让 Lambda 的使用更灵活!