这种处理数据的方式很有用,因为你让Stream API管理如何处理数据。这样StreamAPI就可以在背后进行多种优化。此外,使用内部迭代的话,SteamAPI可以决定并行运行你的代码。这要是用外部迭代的话就办不到了,因为你只能用单一线程挨个迭代。在本章中,你将会看到Stream API支持的许多操作。这些操作能让你快速完成复杂的数据查询,如筛选、切片、映射、查找、匹配和归约。接下来,我们会看看一些特殊的流:数值流、来自文件和数组等多种来源的流,最后是无限流。

5.1 筛选和切片

在本节中,我们来看看如何选择流中的元素:用谓词筛选,筛选出各不相同的元素,忽略流中的头几个元素,或将流截短至指定长度。

5.1.1 用谓词筛选

5.1.3截短流

流支持1imit(n)方法,该方法会返回一个不超过给定长度的流。所需的长度作为参数传递给1imit。如果流是有序的,则最多会返回前n个元素。比如,你可以建立一个list,选出热量超过300卡路里的头三道菜:

Listdishes =men.stream()filter(d->d.getCalories()>300)

limit(3)

collect(toList());

图5-3展示了filter和limit的组合。你可以看到,该方法只选出了符合谓词的头三个元素然后就立即返回了结果。

请注意limit也可以用在无序流上,比如源是一个set。这种情况下,limit的结果不会以任何顺序排列。

5.1.4 跳过元素

流还支持skip(n)方法,返回一个扔掉了前n个元素的流。如果流中元素不足n个,则返回一个空流。请注意,1imit(n)和skip(n)是互补的!例如,下面的代码将跳过超过300卡路里的头两道菜,并返回剩下的。图5-4展示了这个查询。

Listdishes =menu.stream()

filter(d ->d.getCalories()>300)

.skip(2)

.collect(toList())i

在我们讨论映射操作之前,在测验5.1上试试本节学过的内容吧。

测验5.1:筛选

你将如何利用流来筛选前两个荤菜呢” />wordLengths =words.stream()

.map(String::length)

collect(toList())i

现在让我们回到提取菜名的例子。如果你要找出每道菜的名称有多长,怎么做?你可以像下面这样,再链接上一个map: