Java核心技术·卷Ⅱ:高级特性(原书第10版)
上QQ阅读APP看书,第一时间看更新

1.3 filter、map和flatMap方法

流的转换会产生一个新的流,它的元素派生自另一个流中的元素。我们已经看到了filter转换会产生一个流,它的元素与某种条件相匹配。下面,我们将一个字符串流转换为了只包含长单词的另一个流:

filter的引元是Predicate<T>,即从T到boolean的函数。

通常,我们想要按照某种方式来转换流中的值,此时,可以使用map方法并传递执行该转换的函数。例如,我们可以像下面这样将所有单词都转换为小写:

这里,我们使用的是带有方法引用的map,但是,通常我们可以使用lambda表达式来代替:

上面语句所产生的流中包含了所有单词的首字母。

在使用map时,会有一个函数应用到每个元素上,并且其结果是包含了应用该函数后所产生的所有结果的流。现在,假设我们有一个函数,它返回的不是一个值,而是一个包含众多值的流:

例如,letters("boat")的返回值是流["b","o","a","t"]。

注意:通过使用1.13节中的IntStream.range方法,我们实现这个方法可以优雅得多。

假设我们在一个字符串流上映射letters方法:

那么就会得到一个包含流的流,就像[...["y","o","u","r"],["b","o","a","t"],...]。为了将其摊平为字母流[..."y","o","u","r","b","o","a","t",...],可以使用flatMap方法而不是map方法:

注意:在流之外的类中你也会发现flatMap方法,因为它是计算机科学中的一种通用概念。假设我们有一个泛型G(例如Stream),以及将某种类型T转换为G<U>的函数f和将类型U转换为G<V>的函数g。然后,我们可以通过使用flatMap来组合它们,即首先应用f,然后应用g。这是单子论的关键概念。但是不必担心,我们无须了解任何有关单子的知识就可以使用flatMap。

java.util.stream.Stream 8

·Stream<T>filter(Predicate<?super T>predicate)

产生一个流,它包含当前流中所有满足断言条件的元素。

·<R>Stream<R>map(Function<?super T,?extends R>mapper)

产生一个流,它包含将mapper应用于当前流中所有元素所产生的结果。

·<R>Stream<R>f latMap(Function<?super T,?extends Stream<?extends R>>mapper)

产生一个流,它是通过将mapper应用于当前流中所有元素所产生的结果连接到一起而获得的。(注意,这里的每个结果都是一个流。)