如何在 Java 中使用 Lambda 表达式

JavaJavaBeginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

本教程将指导你学习在 Java 中使用 Lambda 表达式的基础知识。你将学习如何利用这一强大功能编写更简洁、更具表现力的代码,并探索在你的 Java 项目中充分发挥 Lambda 潜力的高级技术。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL java(("Java")) -.-> java/ProgrammingTechniquesGroup(["Programming Techniques"]) java(("Java")) -.-> java/ObjectOrientedandAdvancedConceptsGroup(["Object-Oriented and Advanced Concepts"]) java/ProgrammingTechniquesGroup -.-> java/method_overloading("Method Overloading") java/ProgrammingTechniquesGroup -.-> java/method_overriding("Method Overriding") java/ProgrammingTechniquesGroup -.-> java/scope("Scope") java/ProgrammingTechniquesGroup -.-> java/lambda("Lambda") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/classes_objects("Classes/Objects") subgraph Lab Skills java/method_overloading -.-> lab-415587{{"如何在 Java 中使用 Lambda 表达式"}} java/method_overriding -.-> lab-415587{{"如何在 Java 中使用 Lambda 表达式"}} java/scope -.-> lab-415587{{"如何在 Java 中使用 Lambda 表达式"}} java/lambda -.-> lab-415587{{"如何在 Java 中使用 Lambda 表达式"}} java/classes_objects -.-> lab-415587{{"如何在 Java 中使用 Lambda 表达式"}} end

Lambda 表达式简介

什么是 Lambda 表达式?

Lambda 表达式,也称为匿名函数,是在 Java 中表示方法的一种简洁方式。它们允许你通过封装单个方法实现来编写更小、更易读的代码。Lambda 表达式是 Java 8 中引入的一项关键特性,现已成为 Java 语言不可或缺的一部分。

使用 Lambda 表达式的好处

  1. 简洁的语法:与传统的匿名内部类相比,Lambda 表达式提供了更紧凑、易读的语法。
  2. 函数式编程:Lambda 表达式使 Java 能够采用函数式编程风格,从而编写更具表现力和声明性的代码。
  3. 提高可读性:通过去除样板代码,Lambda 表达式使你的代码更易读、更易于理解。
  4. 高效执行:Java 虚拟机(JVM)可以优化 Lambda 表达式的执行,从而提高性能。

Lambda 表达式的结构

一个 Lambda 表达式由以下部分组成:

(参数) -> { 主体 }
  • 参数:Lambda 表达式的参数,括在括号内。参数类型可以选择性地指定。
  • 箭头符号-> 符号,用于分隔参数和 Lambda 表达式的主体。
  • 主体:Lambda 表达式的实现,可以是单个表达式或用花括号 {} 括起来的语句块。

下面是一个 Lambda 表达式的示例,它接受两个整数并返回它们的和:

(int x, int y) -> { return x + y; }

在这个示例中,参数是 (int x, int y),箭头符号是 ->,主体是 { return x + y; }

graph TD A[Lambda 表达式] --> B[参数] A --> C[箭头符号] A --> D[主体] B[参数] --> E[可选指定的类型] D[主体] --> F[单个表达式] D --> G[语句块]

函数式接口

Lambda 表达式旨在与函数式接口配合使用。函数式接口是一个只有一个抽象方法的接口。Lambda 表达式必须与函数式接口中抽象方法的签名兼容。

Java 中最常用的函数式接口之一是 java.util.function.Function<T, R>,它表示一个接受类型为 T 的单个参数并返回类型为 R 的结果的函数。

Function<Integer, Integer> doubler = (x) -> x * 2;
int result = doubler.apply(5); // result = 10

在这个示例中,Lambda 表达式 (x) -> x * 2 被赋给一个 Function<Integer, Integer> 变量,并调用 apply() 方法来调用 Lambda 表达式。

通过理解 Lambda 表达式的基础知识,你将能够利用它们的强大功能编写更简洁、函数式和高效的 Java 代码。在下一节中,我们将探讨如何在 Java 的各种上下文中使用 Lambda 表达式。

在 Java 中使用 Lambda 表达式

函数式接口与 Lambda 表达式

如前所述,Lambda 表达式旨在与函数式接口配合使用。让我们来探讨一下 Lambda 表达式在 Java 中的一些常见用例。

实现函数式接口

使用 Lambda 表达式最直接的方法之一是实现函数式接口。下面是一个使用 Runnable 接口的示例:

Runnable task = () -> {
    System.out.println("任务正在运行...");
};
task.run();

在这个示例中,Lambda 表达式 () -> { System.out.println("任务正在运行..."); } 用于实现 Runnable 接口的 run() 方法。

将 Lambda 表达式作为参数传递

Lambda 表达式可以作为参数传递给接受函数式接口的方法。在处理集合和流时,这特别有用。下面是一个使用 java.util.List 接口的 forEach() 方法的示例:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.forEach(name -> System.out.println(name));

在这个示例中,Lambda 表达式 name -> System.out.println(name) 作为参数传递给 forEach() 方法,该方法将 Lambda 表达式应用于 names 列表中的每个元素。

返回 Lambda 表达式

Lambda 表达式也可以从方法中返回。当你想要创建并返回一个可重用的函数时,这很有用。下面是一个示例:

Function<Integer, Integer> createDoubler() {
    return (x) -> x * 2;
}

Function<Integer, Integer> doubler = createDoubler();
int result = doubler.apply(5); // result = 10

在这个示例中,createDoubler() 方法返回一个 Function<Integer, Integer> Lambda 表达式,该表达式将其输入加倍。

高级 Lambda 技术

方法引用

你可以使用方法引用而不是 Lambda 表达式来引用现有方法。方法引用提供了一种更简洁的方式来表达相同的功能。下面是一个示例:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.forEach(System.out::println);

在这个示例中,使用方法引用 System.out::println 代替了 Lambda 表达式 name -> System.out.println(name)

捕获局部变量

Lambda 表达式可以访问和使用封闭作用域中的变量,包括它们所定义的方法中的局部变量。这些变量实际上被视为 final 或有效 final(如果它们没有被显式声明为 final)。下面是一个示例:

int multiplier = 2;
Function<Integer, Integer> createMultiplier(int factor) {
    return (x) -> x * factor;
}

Function<Integer, Integer> doubler = createMultiplier(multiplier);
int result = doubler.apply(5); // result = 10

在这个示例中,Lambda 表达式 (x) -> x * factor 捕获了 createMultiplier() 方法中的 factor 参数。

通过理解这些技术,你将能够利用 Lambda 表达式的强大功能编写更简洁、函数式和高效的 Java 代码。

高级 Lambda 技术

方法引用

如前所述,方法引用提供了一种比 Lambda 表达式更简洁的方式来表达相同的功能。你可以使用方法引用而不是 Lambda 表达式来引用现有方法。

下面是一个示例:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.forEach(System.out::println);

在这个示例中,使用方法引用 System.out::println 代替了 Lambda 表达式 name -> System.out.println(name)

方法引用可以用于以下形式:

  • 类::静态方法
  • 对象::实例方法
  • 类::实例方法
  • 类::新建

捕获局部变量

Lambda 表达式可以访问和使用封闭作用域中的变量,包括它们所定义的方法中的局部变量。这些变量实际上被视为 final 或有效 final(如果它们没有被显式声明为 final)。

下面是一个示例:

int multiplier = 2;
Function<Integer, Integer> createMultiplier(int factor) {
    return (x) -> x * factor;
}

Function<Integer, Integer> doubler = createMultiplier(multiplier);
int result = doubler.apply(5); // result = 10

在这个示例中,Lambda 表达式 (x) -> x * factor 捕获了 createMultiplier() 方法中的 factor 参数。

流与并行处理

Java 8 引入了 Stream API,它允许你对数据集合执行函数式风格的操作。Lambda 表达式通常与流一起使用,以创建更具表现力和简洁的代码。

下面是一个将 Lambda 表达式与流一起使用的示例:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> doubledNumbers = numbers.stream()
                                    .map(x -> x * 2)
                                    .collect(Collectors.toList());

在这个示例中,Lambda 表达式 x -> x * 2 用作 map() 方法的参数,该方法将加倍操作应用于流中的每个元素。

此外,可以使用 parallelStream() 方法对流进行并行处理,这对于某些类型的操作可以显著提高性能。下面是一个示例:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
List<Integer> doubledNumbers = numbers.parallelStream()
                                    .map(x -> x * 2)
                                    .collect(Collectors.toList());

在这个示例中,parallelStream() 方法用于并行处理流,可能会提高加倍操作的性能。

通过理解这些高级 Lambda 技术,你将能够编写更具表现力、简洁和高效的 Java 代码,充分利用函数式编程的强大功能。

总结

在本教程结束时,你将对如何在 Java 中使用 Lambda 表达式有扎实的理解。通过利用 Lambda,你将能够编写更高效、更易读的代码,并探索在你的 Java 应用程序中利用这一强大功能的高级技术。