# 问题和练习：聚合操作

> 原文： [https://docs.oracle.com/javase/tutorial/collections/streams/QandE/questions.html](https://docs.oracle.com/javase/tutorial/collections/streams/QandE/questions.html)

## 问题

1.  一系列聚合操作称为 ___。
2.  每个管道包含零个或多个 ___ 操作。
3.  每个管道以 ___ 操作结束。
4.  什么样的操作产生另一个流作为其输出？
5.  描述`forEach`聚合操作与增强`for`语句或迭代器不同的一种方式。
6.  对错：流类似于集合，因为它是存储元素的数据结构。
7.  识别此代码中的中间和终端操作：

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

    ```

8.  代码 `p -&gt; p.getGender() == Person.Sex.MALE` 是什么样的例子？
9.  代码 `Person::getAge` 是什么样的例子？
10.  组合流内容并返回一个值的终端操作被称为什么？
11.  列举`Stream.reduce`方法和`Stream.collect`方法之间的一个重要区别。
12.  如果要处理名称流，提取男性名称，并将它们存储在新的`List`中，`Stream.reduce`或`Stream.collect`是否最适合使用？
13.  判断对错：聚合操作可以实现与非线程安全集合的并行性。
14.  除非另有说明，否则流始终是串行的。您如何请求并行处理流？

## 演习

1.  将以下增强`for`语句写为具有 lambda 表达式的管道。提示：使用`filter`中间操作和`forEach`端子操作。

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

    ```

2.  将以下代码转换为使用 lambda 表达式和聚合操作而不是嵌套`for`循环的新实现。提示：按此顺序创建一个调用`filter`，`sorted`和`collect`操作的管道。

    ```
    List&lt;Album&gt; favs = new ArrayList&lt;&gt;();
    for (Album a : albums) {
        boolean hasFavorite = false;
        for (Track t : a.tracks) {
            if (t.rating &gt;= 4) {
                hasFavorite = true;
                break;
            }
        }
        if (hasFavorite)
            favs.add(a);
    }
    Collections.sort(favs, new Comparator&lt;Album&gt;() {
                               public int compare(Album a1, Album a2) {
                                   return a1.name.compareTo(a2.name);
                               }});

    ```

[检查你的答案。](answers.html)