ZetCode

Java Lambda 表达式

最后修改时间:2025 年 4 月 17 日

Lambda 表达式是 Java 8 中引入的,是 Java 中函数式编程的基石。它们允许开发人员通过提供函数式接口的内联实现来编写简洁、富有表现力的代码。本教程探讨它们的语法、用例和实际应用。

本教程探讨 Java lambda 表达式,它是 Java 8 中引入的一项强大功能,可以实现简洁而富有表现力的函数式编程。 Lambda 表达式简化了函数式接口的实现,并简化了排序、过滤和映射数据等操作。

Java 中 lambda 表达式的基本语法如下:

(parameters) -> expression
(parameters) -> { statements; }

Lambda 表达式提高了代码的可读性和简洁性,使开发人员能够编写更易于维护和高效的 Java 应用程序。

参数类型声明是可选的; Java 编译器可以从上下文中推断类型。对于单个参数,括号是可选的,但对于多个参数或没有参数,括号是必需的。对于单语句主体,花括号是可选的,如果主体由返回值的单个表达式组成,则不需要 return 关键字。但是,当使用多个语句显式返回值时,花括号是必需的。

对数组进行排序

排序数组是编程中的常见任务,lambda 表达式通过提供一种简洁的方式来定义比较逻辑,从而使其变得更容易。以下示例演示了使用 lambda 表达式按字母顺序对字符串数组进行排序。

com/zetcode/LambdaSortEx.java
package com.zetcode;

import java.util.Arrays;

public class LambdaSortEx {

    public static void main(String[] args) {

        String[] words = { "kind", "massive", "atom", "car", "blue" };

        Arrays.sort(words, (s1, s2) -> s1.compareTo(s2));

        System.out.println(Arrays.toString(words));
    }
}

此示例演示了如何使用带有 lambda 表达式的 Arrays.sort 方法对字符串数组进行排序。 lambda 表达式 (s1, s2) -> s1.compareTo(s2) 定义了比较逻辑,从而生成按字母顺序排序的数组。

$ java com/zetcode/LambdaSortEx.java
[atom, blue, car, kind, massive]

函数式接口和 Lambda 表达式

函数式接口(包含单个抽象方法)是 Java 中 lambda 表达式的基础。 Lambda 表达式提供了一种紧凑的方式来实现这些接口,从而实现灵活且可重用的代码结构。

实现问候服务

创建自定义函数式接口允许开发人员定义特定的行为。此示例演示了如何使用 lambda 表达式来实现一个简单的问候服务,该服务将消息输出到控制台。

com/zetcode/LambdaGreetingEx.java
package com.zetcode;

interface GreetingService {
    void greet(String message);
}

public class LambdaGreetingEx {

    public static void main(String[] args) {

        GreetingService gs = msg -> System.out.println(msg);

        gs.greet("Good night");
        gs.greet("Hello there");
    }
}

在此示例中,定义了一个具有单个 greet 方法的 GreetingService 函数式接口。 lambda 表达式实现了此接口,并在调用 greet 方法时将消息打印到控制台。

$ java com/zetcode/LambdaGreetingEx.java
Good night
Hello there

常见的函数式接口

java.util.function 包提供了一组内置的函数式接口,例如 FunctionConsumerSupplierPredicate。这些接口支持常见的函数式编程模式,使 lambda 表达式更加通用。

使用 Function 接口

Function 接口非常适合于接受输入并产生输出的操作。此示例使用 lambda 表达式来定义一个计算整数平方的函数。

com/zetcode/LambdaFunctionEx.java
package com.zetcode;

import java.util.function.Function;

public class LambdaFunctionEx {

    public static void main(String[] args) {

        Function square = x -> x * x;
        System.out.println(square.apply(5));
    }
}

此示例使用 Function 接口来定义一个计算整数平方的 lambda 表达式。 apply 方法执行 lambda,返回结果。

$ java com/zetcode/LambdaFunctionEx.java
25

使用流过滤数据

Java 流与 lambda 表达式相结合,提供了一种强大的数据集合处理方式。此示例演示了基于 lambda 表达式定义的条件过滤对象列表。

com/zetcode/LambdaFilterEx.java
package com.zetcode;

import java.util.List;
import java.util.stream.Collectors;

public class LambdaFilterEx {

    public static void main(String[] args) {

        List<User> persons = List.of(
                new User("Jack", "jack234@gmail.com"),
                new User("Peter", "pete2@post.com"),
                new User("Lucy", "lucy17@gmail.com"),
                new User("Robert", "bob56@post.com"),
                new User("Martin", "mato4@imail.com")
        );

        List<User> result = persons.stream()
                .filter(person -> person.email().matches(".*post\\.com"))
                .collect(Collectors.toList());

        result.forEach(p -> System.out.println(p.name()));
    }
}

record User(String name, String email) {}

此示例在流中使用 lambda 表达式来根据其电子邮件域名过滤 User 对象。 filter 方法中的 lambda 表达式选择电子邮件以“post.com”结尾的用户,而 forEach 中的另一个 lambda 表达式则打印其姓名。

$ java com/zetcode/LambdaFilterEx.java
Peter
Robert

使用流映射数据

Java 流中的 map 方法允许开发人员使用 lambda 表达式转换数据。此示例演示了如何将字符串列表转换为其长度的列表。

com/zetcode/LambdaMapEx.java
package com.zetcode;

import java.util.List;
import java.util.stream.Collectors;

public class LambdaMapEx {

    public static void main(String[] args) {

        List<String> words = List.of("apple", "banana", "cherry");

        List<Integer> lengths = words.stream()
                .map(word -> word.length())
                .collect(Collectors.toList());

        System.out.println(lengths);
    }
}

此示例演示了如何将 lambda 表达式与 map 方法结合使用,以将字符串列表转换为其长度的列表。 lambda word -> word.length() 计算每个单词的长度。

$ java com/zetcode/LambdaMapEx.java
[5, 6, 6]

使用 Consumer 接口

Consumer 接口用于接受输入但不产生输出的操作,例如打印或修改数据。此示例使用 lambda 表达式来打印大写字符串。

com/zetcode/LambdaConsumerEx.java
package com.zetcode;

import java.util.function.Consumer;

public class LambdaConsumerEx {

    public static void main(String[] args) {

        Consumer<String> printUpperCase = text -> System.out.println(text.toUpperCase());

        printUpperCase.accept("hello");
        printUpperCase.accept("java lambda");
    }
}

此示例使用 Consumer 接口来定义一个 lambda 表达式,该表达式将字符串转换为大写并将其打印出来。 accept 方法触发 lambda 的执行。

$ java com/zetcode/LambdaConsumerEx.java
HELLO
JAVA LAMBDA

使用 Supplier 接口

Supplier 接口用于生成值而不接受任何输入。此示例演示了一个生成随机问候语的 lambda 表达式。

com/zetcode/LambdaSupplierEx.java
package com.zetcode;

import java.util.function.Supplier;

public class LambdaSupplierEx {

    public static void main(String[] args) {

        Supplier<String> randomGreeting = () -> {
            String[] greetings = {"Hello", "Hi", "Greetings"};
            return greetings[(int) (Math.random() * greetings.length)];
        };

        System.out.println(randomGreeting.get());
        System.out.println(randomGreeting.get());
    }
}

此示例使用 Supplier 接口来创建一个 lambda 表达式,该表达式返回随机问候语。 get 方法检索由 lambda 产生的值。

$ java com/zetcode/LambdaSupplierEx.java
Hi
Greetings

组合谓词

Predicate 接口用于测试条件。此示例演示了如何使用逻辑运算组合多个谓词来过滤数据。

com/zetcode/LambdaPredicateEx.java
package com.zetcode;

import java.util.List;
import java.util.function.Predicate;

public class LambdaPredicateEx {

    public static void main(String[] args) {

        List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7, 8);

        Predicate<Integer> isEven = n -> n % 2 == 0;
        Predicate<Integer> isGreaterThanFour = n -> n > 4;

        List<Integer> result = numbers.stream()
                .filter(isEven.and(isGreaterThanFour))
                .toList();

        System.out.println(result);
    }
}

此示例组合了两个 Predicate lambda 表达式来过滤数字列表,仅选择大于 4 的偶数。 and 方法以逻辑方式组合了这些谓词。

$ java com/zetcode/LambdaPredicateEx.java
[6, 8]

来源

有关更多阅读材料,请参阅有关 lambda 表达式的官方 Java 文档,该文档提供了对其语法和应用的详细见解。

Java Lambda 表达式文档

本教程提供了 Java lambda 表达式的全面概述,包括其语法、与函数式接口的用法以及在排序、过滤、映射等方面的实际应用。

作者

我叫 Jan Bodnar,是一位敬业的程序员,在软件开发方面拥有丰富的经验。自 2007 年以来,我撰写了 1,400 多篇编程文章和八本电子书。凭借十多年的教学经验,我致力于分享知识并培养对编程概念的更深入的理解。

列出所有Java教程