Java中的Lambda表达式与Stream API | AI生成和翻译

Home 2025.03

好的,让我们来学习 Java 中的 Lambda 表达式和 Stream API。这些是 Java 8 引入的强大特性,支持更具函数式的编程风格,从而使代码更简洁、更具表达力。

1. Lambda 表达式

什么是 Lambda 表达式?

Lambda 表达式本质上是一个匿名(未命名)函数。它允许您内联定义一个函数,而无需显式声明一个单独的方法。Lambda 表达式在将行为作为数据传递时特别有用,使您的代码更加灵活和可读,尤其是在使用函数式接口时。

Lambda 表达式的语法:

Lambda 表达式具有以下基本语法:

(参数列表) -> 表达式主体

函数式接口:

Java 中的 Lambda 表达式用于实现由函数式接口定义的方法。函数式接口是仅包含一个抽象方法的接口。它可以有默认方法和静态方法,但只能有一个抽象方法。

Java 中内置的函数式接口示例包括:

Lambda 表达式示例:

让我们看一些例子来理解 Lambda 表达式是如何工作的:

方法引用:

方法引用是 Lambda 表达式的一种简写语法,它只是调用一个现有的方法。它们使您的代码更加简洁。方法引用有四种:

  1. 引用静态方法: ClassName::staticMethodName

    java.util.function.Function<String, Integer> stringToInt = Integer::parseInt;
    int number = stringToInt.apply("123"); // number 将为 123
    
  2. 引用特定对象的实例方法: instance::instanceMethodName

    String message = "Hello";
    java.util.function.Consumer<String> printLength = message::length; // 错误 - Consumer 接受一个参数
    java.util.function.Supplier<Integer> getLength = message::length;
    int len = getLength.get(); // len 将为 5
    

    更正: Consumer 示例应该接受一个参数。这里是一个更好的例子:

    String message = "Hello";
    java.util.function.Consumer<String> printContains = s -> message.contains(s);
    printContains.accept("ll"); // 这将执行 message.contains("ll")
    

    对于 Supplier,它更像是:

    String message = "Hello";
    java.util.function.Supplier<Integer> getLength = message::length;
    int len = getLength.get(); // len 将为 5
    
  3. 引用特定类型的任意对象的实例方法: ClassName::instanceMethodName

    java.util.function.BiPredicate<String, String> checkStartsWith = String::startsWith;
    boolean starts = checkStartsWith.test("Java", "Ja"); // starts 将为 true
    
  4. 引用构造函数: ClassName::new

    java.util.function.Supplier<String> createString = String::new;
    String emptyString = createString.get(); // emptyString 将为 ""
    
    java.util.function.Function<Integer, int[]> createIntArray = int[]::new;
    int[] myArray = createIntArray.apply(5); // myArray 将是一个大小为 5 的 int 数组
    

2. Stream API

什么是 Stream API?

Stream API 在 Java 8 中引入,提供了一种强大而优雅的方式来处理数据集合。流代表一个支持各种聚合操作的元素序列。流与集合不同;集合是关于存储数据的,而流是关于处理数据的。

Stream API 的关键概念:

创建流:

您可以通过多种方式创建流:

中间操作:

这些操作转换或过滤流并返回一个新流。常见的中间操作包括:

终止操作:

这些操作产生结果或副作用并消费流。常见的终止操作包括:

3. Lambda 表达式与 Stream 的关系

Lambda 表达式大量用于 Stream API。它们为许多中间操作和终止操作定义行为提供了一种简洁的方式。例如,filter() 中的 Predicatemap() 中的 FunctionforEach() 中的 Consumer 通常使用 Lambda 表达式来实现。

结合使用 Lambda 表达式和 Stream 的示例:

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

public class LambdaStreamExample {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David", "Eve");

        // 过滤以 'A' 开头的名字并将它们转换为大写
        List<String> aNamesUppercase = names.stream()
                .filter(name -> name.startsWith("A")) // 用于过滤的 Lambda 表达式
                .map(String::toUpperCase)             // 用于映射的方法引用
                .collect(Collectors.toList());

        System.out.println("Names starting with 'A' in uppercase: " + aNamesUppercase);
        // 输出: Names starting with 'A' in uppercase: [ALICE]

        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        // 查找偶数的平方和
        int sumOfSquaresOfEvens = numbers.stream()
                .filter(n -> n % 2 == 0)       // 用于过滤偶数的 Lambda 表达式
                .map(n -> n * n)              // 用于平方的 Lambda 表达式
                .reduce(0, Integer::sum);     // 用于求和的方法引用

        System.out.println("Sum of squares of even numbers: " + sumOfSquaresOfEvens);
        // 输出: Sum of squares of even numbers: 220

        List<Person> people = Arrays.asList(
                new Person("Alice", 30),
                new Person("Bob", 25),
                new Person("Charlie", 35)
        );

        // 获取年龄大于 28 岁的人员姓名列表
        List<String> olderPeopleNames = people.stream()
                .filter(person -> person.getAge() > 28) // 用于过滤的 Lambda 表达式
                .map(Person::getName)                 // 用于获取姓名的方法引用
                .collect(Collectors.toList());

        System.out.println("Names of people older than 28: " + olderPeopleNames);
        // 输出: Names of people older than 28: [Alice, Charlie]
    }
}

class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

4. 并行流

Stream API 还支持并行处理。您可以使用集合上的 parallelStream() 方法,或者通过在顺序流上调用 parallel() 方法,轻松地并行处理流的元素。对于大型数据集上的某些操作,这可以显著提高性能。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

// 并行计算平方和
int sumOfSquaresParallel = numbers.parallelStream()
        .map(n -> n * n)
        .reduce(0, Integer::sum);

System.out.println("Sum of squares (parallel): " + sumOfSquaresParallel);

结论

Lambda 表达式和 Stream API 是 Java 的强大补充,支持一种更具函数式风格且更简洁的编码方式,尤其是在处理数据集合时。通过将 Lambda 表达式与 Stream 结合使用,您可以以声明性和可读性强的方式执行复杂的数据处理操作。理解这些特性对于现代 Java 开发至关重要。记住要多加练习使用它们,以变得更加熟练和精通。


Back Donate