类:汇总操作

注意 :要更好地理解本节中的概念,请查看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 循环的版本 Long,但是您将看到使用批量数据操作的版本对于更复杂的任务将更加简洁。

涵盖以下主题:

在示例BulkDataOperationsExamples中找到本节中描述的代码摘录。

管道和流

管道是一系列聚合操作。以下示例使用包含聚合操作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());
    }
}

管道包含以下组件:

filter操作返回一个新流,该流包含与其谓词(此操作的参数)匹配的元素。在此示例中,谓词是 lambda 表达式e -> e.getGender() == Person.Sex.MALE。如果对象egender字段具有值Person.Sex.MALE,则返回布尔值true。因此,此示例中的filter操作返回一个流,该流包含集合roster中的所有男性成员。

下面的示例使用由聚合操作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部分。

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

聚合操作(如forEach)看起来像迭代器。但是,它们有几个基本差异:

首页