文档

Java™ 教程-Java Tutorials 中文版
聚合操作
Trail: Collections

课程:聚合操作

注意:要更好地理解本节中的概念,请查看 Lambda ExpressionsMethod References 部分。

你用什么集合?你不是简单地将对象存储在集合中并将其保留在那里。在大多数情况下,你使用集合来获取存储在其中的项目。

再次考虑 Lambda Expressions 部分中描述的场景。假设你正在创建社交网络应用程序。你希望创建一项功能,使管理员能够对满足特定条件的社交网络应用程序成员执行任何类型的操作,例如发送消息。

和以前一样,假设此社交网络应用程序的成员由以下 Person 类表示:

public class Person {

    public enum Sex {
        MALE, FEMALE
    }

    String name;
    LocalDate birthday;
    Sex gender;
    String emailAddress;
    
    // ...

    public int getAge() {
        // ...
    }

    public String getName() {
        // ...
    }
}

以下示例使用 for-each 循环打印集合 roster 中包含的所有成员的名称:

for (Person p : roster) {
    System.out.println(p.getName());
}

以下示例打印集合 roster 中包含的所有成员,但使用聚合操作 forEach

roster
    .stream()
    .forEach(e -> System.out.println(e.getName());

虽然在此示例中,使用聚合操作的版本比使用 for-each 循环的版本长,但你会看到使用批量数据操作的版本对于更复杂的任务将更简洁。

涵盖以下主题:

在示例 BulkDataOperationsExamples 中查找本节中描述的代码片段。

管道和流

pipeline 是一系列聚合操作。以下示例使用由聚合操作 filterforEach 组成的管道打印集合 roster 中包含的男性成员:

roster
    .stream()
    .filter(e -> e.getGender() == Person.Sex.MALE)
    .forEach(e -> System.out.println(e.getName()));

将此示例与以下内容进行比较,使用 for-each 循环打印集合 roster 中包含的男性成员:

for (Person p : roster) {
    if (p.getGender() == Person.Sex.MALE) {
        System.out.println(p.getName());
    }
}

管道包含以下组件:

以下示例使用由聚合操作 filtermapToIntaverage 组成的管道计算集合 roster 中包含的所有男性成员的平均年龄:

double average = roster
    .stream()
    .filter(p -> p.getGender() == Person.Sex.MALE)
    .mapToInt(Person::getAge)
    .average()
    .getAsDouble();

mapToInt 操作返回类型为 IntStream 的新流(这是一个仅包含整数值的流)。该操作将其参数中指定的函数应用于特定流中的每个元素。在此示例中,函数是 Person::getAge,它是一个返回成员年龄的方法引用。(或者,你可以使用 lambda 表达式 e -> e.getAge()。)因此,此示例中的 mapToInt 操作返回一个流包含roster 集合中所有男性成员的年龄。

average 操作计算 IntStream 类型流中包含的元素的平均值。它返回一个 OptionalDouble 类型的对象。如果流不包含任何元素,则 average 操作返回 OptionalDouble 的空实例,并且调用方法 getAsDouble 会抛出 NoSuchElementException。JDK 包含许多终端操作,例如 average,它通过组合流的内容返回一个值。这些操作称为 reduction operations (还原操作);有关详细信息,请参阅 Reduction 部分。

聚合操作和迭代器之间的差异

聚合操作,如 forEach,看起来像迭代器。但是,它们有几个根本区别:


Previous page: Previous Lesson
Next page: Reduction