跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava

Java Lambda 表达式详解

Java 8 引入的 Lambda 表达式允许通过表达式代替功能接口,简化匿名内部类写法。其核心是函数式接口(仅含一个抽象方法)。语法上支持省略参数类型、括号及大括号。Lambda 可捕获 final 或 effectively final 的局部变量,直接访问成员变量。在集合操作中结合 Stream API 提升代码简洁性与并行处理能力。优点包括代码简洁、促进函数式编程;缺点涉及学习成本、调试难度及特定场景下的性能开销。

云朵棉花糖发布于 2026/3/23更新于 2026/10/2326K 浏览
Java Lambda 表达式详解

Java Lambda 表达式详解

引入

Lambda 表达式是 Java SE 8 中一个重要的新特性。Lambda 表达式允许你通过表达式来代替功能接口。Lambda 表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体(body,可以是一个表达式或一个代码块)。Lambda 表达式可以看作是一个匿名函数。

语法

基本语法:(parameters) -> expression 或 (parameters) -> { statements; }

Lambda 表达式由三部分组成:

  1. parameters:类似方法中的形参列表,这里的参数是函数式接口里的参数。这里的参数类型可以明确的声明也可不声明而由 JVM 隐含的推断。另外当只有一个推断类型时可以省略掉圆括号。
  2. ->:可理解为'被用于'的意思;
  3. 方法体:可以是表达式也可以代码块,是函数式接口里方法的实现。代码块可返回一个值或者什么都不返回,这里的代码块等同于方法的方法体。如果是表达式,也可以返回一个值或者什么都不返回。

函数式接口

要了解 Lambda 表达式,首先需要了解什么是函数式接口。

函数式接口定义:一个接口有且只有一个抽象方法。

注意:

  1. 如果一个接口只有一个抽象方法,那么该接口就是一个函数式接口。
  2. 如果我们在某个接口上声明了@FunctionalInterface 注解,那么编译器就会按照函数式接口的定义来要求该接口,这样如果有两个抽象方法,程序编译就会报错的。所以,从某种意义上来说,只要你保证你的接口中只有一个抽象方法,你可以不加这个注解。加上就会自动进行检测的。
@FunctionalInterface interface NoParameterNoReturn { void test(); }
@FunctionalInterface interface NoParameterNoReturn { void test(); default void test2(){ System.out.println("JDK 1.8 新特性,default 默认方法可以有具体的实现"); } }

Lambda 表达式的使用

Lambda 表达式本质是一个匿名函数,函数的方法是:返回值 方法名 参数列表 方法体。在 Lambda 表达式中我们只需要关心:参数列表 方法体。

语法精简

  1. 参数类型可以省略,如果需要省略,每个参数的类型都要省略。
  2. 参数的小括号里面只有一个参数,那么小括号可以省略。
  3. 如果方法体当中只有一句代码,那么大括号可以省略。
  4. 如果方法体中只有一条语句,要么是输出语句,其次是 return 语句,那么大括号可以省略,且去掉 return 关键字。

代码示例

//无返回值无参数
@FunctionalInterface interface  {  ; }

   {  ; }

   {  ; }

   {  ; }

   {  ; }

   {  ; }

   {
        {
        
        
        
        
        
        
        
           (x,y) -> System.out.println(x+y);
        moreParameterNoReturn.test(,);
    }
}
NoParameterNoReturn
void
test
()
//无返回值一个参数
@FunctionalInterface
interface
OneParameterNoReturn
void
test
(int a)
//无返回值多个参数
@FunctionalInterface
interface
MoreParameterNoReturn
void
test
(int a,int b)
//有返回值无参数
@FunctionalInterface
interface
NoParameterReturn
int
test
()
//有返回值一个参数
@FunctionalInterface
interface
OneParameterReturn
int
test
(int a)
//有返回值多参数
@FunctionalInterface
interface
MoreParameterReturn
int
test
(int a,int b)
public
class
Test
public
static
void
main
(String[] args)
/*NoParameterNoReturn noParameterNoReturn = ()->System.out.println("test....."); noParameterNoReturn.test();*/
/*OneParameterNoReturn oneParameterNoReturn = (x) -> { System.out.println(x); };*/
/*OneParameterNoReturn oneParameterNoReturn = x -> System.out.println(x); oneParameterNoReturn.test(10);*/
/*MoreParameterNoReturn moreParameterNoReturn = (int x,int y) -> { System.out.println(x+y); };*/
/*OneParameterReturn oneParameterReturn = a -> a; System.out.println(oneParameterReturn.test(10));*/
/* NoParameterReturn noParameterReturn = ()->{return 10;}; */
/* NoParameterReturn noParameterReturn = ()-> 10; System.out.println(noParameterReturn.test());*/
MoreParameterNoReturn
moreParameterNoReturn
=
10
20

变量捕获

在 Java 中,Lambda 表达式允许以更简洁的方式实现接口中的方法。Lambda 表达式可以捕获其所在上下文中有效的 final 或 effectively final(实际上 final,即在 Lambda 表达式内部没有被修改)的局部变量和成员变量。这种捕获机制使得 Lambda 表达式能够访问和使用这些变量,而无需显式地将它们作为参数传递给 Lambda 表达式。

局部变量捕获

对于局部变量,Lambda 表达式只能捕获那些被声明为 final 或者实际上未被修改的变量(effectively final)。这意味着即使变量没有被显式地声明为 final,但如果你在 Lambda 表达式之外没有修改这个变量的值,那么这个变量也可以被 Lambda 表达式捕获。

public class LambdaDemo {
    public static void main(String[] args) {
        final int number = 10; // 显式声明为 final
        int anotherNumber = 20; // 实际上 final,因为之后没有被修改
        // 使用 Lambda 表达式
        Runnable r = () -> System.out.println(number); // 可以捕获 number
        // Runnable r = () -> System.out.println(anotherNumber); // 也可以捕获 anotherNumber
        // 如果尝试修改 anotherNumber,则上面的 Lambda 表达式将无法编译
        // anotherNumber = 30;
        r.run();
    }
}

成员变量捕获

与局部变量不同,Lambda 表达式可以直接访问所在类的成员变量,无论这些成员变量是否被声明为 final。这是因为成员变量是类的属性,它们的生命周期与类的实例相同,而 Lambda 表达式只是类的实例的一个方法或者构造器中的一部分。

public class LambdaDemo {
    private int classVariable = 42;
    public void display() {
        Runnable r = () -> System.out.println(classVariable); // 直接访问成员变量
        r.run();
    }
    public static void main(String[] args) {
        new LambdaDemo().display();
    }
}

总结

  1. Lambda 表达式内部不能修改捕获的局部变量(除非这些变量是数组或集合的元素,并且通过引用访问这些元素)。
  2. Lambda 表达式可以捕获并访问类的成员变量和静态变量,无需任何限制。
  3. Java 8 及以上版本支持 Lambda 表达式。

Lambda 在集合中的使用

为了能够让 Lambda 和 Java 的集合类集更好的一起使用,集合当中,也新增了部分接口,以便与 Lambda 表达式对接。

对应的接口新增的方法
CollectionremoveIf(), spliterator(), stream(), parallelStream(), forEach()
ListreplaceAll(), sort()
MapgetOrDefault(), forEach(), replaceAll(), putIfAbsent(), remove(), replace(), merge()

代码示例

public class Test2 {
    public static void main(String[] args) {
        Map<String,Integer> map = new HashMap<>();
        map.put("hello",13);
        map.put("abc",3);
        map.put("zhangsan",31);
        /*map.forEach(new BiConsumer<String, Integer>() {
            @Override
            public void accept(String s, Integer integer) {
                System.out.println("key: "+s +" val: "+integer);
            }
        });*/
        map.forEach((s, integer) -> System.out.println("key: "+s +" val: "+integer));
    }
    public static void main1(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("hello");
        list.add("abc");
        list.add("zhangsan");
        /*list.forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        });*/
        list.forEach(s -> System.out.println(s));
        /* list.sort(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o1.compareTo(o2);
            }
        });*/
        list.sort((o1, o2) -> o1.compareTo(o2));
        System.out.println("====");
        list.forEach(s -> System.out.println(s));
    }
}

Lambda 的优缺点

优点

  1. 代码简洁性:Lambda 表达式可以使得代码更加简洁易读,尤其是当实现简单的接口时。相比传统的匿名内部类,Lambda 表达式在语法上更加简洁。
  2. 增强功能性接口的使用:Lambda 表达式常与功能性接口(Functional Interface,即只包含一个抽象方法的接口)一起使用,使得这些接口的实现变得更加容易和直观。
  3. 易于并行计算:Java 8 的 Streams API 与 Lambda 表达式相结合,使得数据集的并行处理变得简单而高效。开发者可以轻松地将顺序操作转换为并行操作,从而提高程序的执行效率。
  4. 促进函数式编程风格:Lambda 表达式和 Streams API 等特性促进了 Java 中函数式编程风格的应用,使得 Java 不再仅仅是面向对象的编程语言,也可以用于实现更加灵活的函数式编程范式。
  5. 提升 API 的设计:Lambda 表达式使得 API 的设计更加灵活和强大。开发者可以设计出更加通用和灵活的接口,以适应不同的使用场景。

缺点

  1. 学习曲线:对于习惯于传统 Java 编程范式的开发者来说,Lambda 表达式和 Streams API 等新特性可能需要一定的时间来学习和适应。
  2. 调试难度:由于 Lambda 表达式在语法上的简洁性,有时候可能会使得调试变得更加困难。尤其是在复杂的 Lambda 表达式中,追踪错误来源可能会比较棘手。
  3. 性能开销:虽然 Lambda 表达式在大多数情况下不会对性能产生显著影响,但在某些极端情况下(如大量使用 Lambda 表达式和 Streams API 进行密集计算),可能会引入一定的性能开销。这是因为 Lambda 表达式和 Streams API 的底层实现可能需要更多的内存和 CPU 资源。
  4. 可读性和可维护性:虽然 Lambda 表达式可以使代码更加简洁,但在某些情况下,过度使用或滥用 Lambda 表达式可能会降低代码的可读性和可维护性。例如,过于复杂的 Lambda 表达式可能会使得其他开发者难以理解其逻辑。
  5. 限制了变量的使用:Lambda 表达式内部只能访问标记为 final 或 effectively final 的局部变量。这一限制可能会在某些情况下造成不便,尤其是当需要在 Lambda 表达式内部修改外部变量时。

目录

  1. Java Lambda 表达式详解
  2. 引入
  3. 语法
  4. 函数式接口
  5. Lambda 表达式的使用
  6. 语法精简
  7. 代码示例
  8. 变量捕获
  9. 局部变量捕获
  10. 成员变量捕获
  11. 总结
  12. Lambda 在集合中的使用
  13. 代码示例
  14. Lambda 的优缺点
  15. 优点
  16. 缺点

更多推荐文章

查看全部
  • Java 部署:Jenkins Pipeline 自动化构建 Java 项目
  • 《Agent Runtime 工程化》第四章 工具系统设计:4.7 动手任务
  • Python 转行职业规划与核心岗位技能分析
  • OpenWebUI 联网搜索实战:用 SearXNG 让本地大模型获取实时信息
  • 详解高速 ADC 的串行 LVDS 数据捕获与接口设计
  • JavaAI 插件安装与 Spring Boot 项目生成实战
  • 算法实战:Z 字形变换与外观数列模拟解法
  • 大模型开发框架 LangChain 入门与实战
  • 深度优先搜索(DFS)与回溯法:全排列与子集问题的决策树及剪枝优化
  • OpenClaw Self-Improving 技能解析:从 SKILL.md 看 AI 自我进化逻辑
  • 前端地图开发基础:服务类型、坐标系与 SDK 选型指南
  • 基于 HarmonyOS 6 的共享终端全链路隐私保护实战
  • 5 种常见运维场景的 Python 脚本实现
  • 上海交大《动手学大模型应用开发》入门指南
  • OpenClaw Luna:VS Code 中的 AI Agent 管理扩展
  • Python+AI 入门指南:从零基础到实操落地与避坑
  • Manacher(马拉车)算法详解:求解最长回文子串
  • MonkeyCode 全流程 AI 编程协作工具技术解析
  • Git 分支管理完全指南:从创建、合并到冲突解决
  • 基于 Claude Code、DeepSeek 与 OpenSpec 实现自动化代码生成教程

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online