一个非常常见的数据处理套路就是从某些对象中选择信息。
比如在SQL里,你可以从表中选择一列。
Stream API也通过map和flatMap方法提供了类似的工具。

1、对流中每一个元素应用函数

流支持map方法,它会接受一个函数作为参数。
这个函数会被应用到每个元素上,并将其映射成一个新的元素
(使用映射一词,是因为它和转换类似,但其中的细微差别在于它是“创建一个新版本”而不是去“修改”)。
例如,下面的代码把方法引用Dish: :getName传给了map方法,来提取流中菜肴的名称:
P}OGRSW8(NSR2)R5IIK3$UM.png
因为getName方法返回一个string,所以map方法输出的流的类型就是stream
再看一个稍微不同的例子。
给定一个单词列表,你想要返回另一个列表, 显示每个单词中有几个字母。
怎么做呢?
需要对列表中的每个元素应用一个函数。
应用的函数应该接受一个单词,并返回其长度。
4MY)E@~F53W@5D@4N856P9M.png

2、流的扁平化

拓展一下对于一张单词表,如何返回一张列表,列出里面各不相同的字符呢?
例如,给定单词列表[“Hello”, “World”],你想要返回列表[“H”, “e”, “1”,”o”, “W” , “r”, “d”]。
你可能会认为这很容易,你可以把每个单词映射成一张字符表, 然后调用distinct来过滤重复的字符。
第一个版本可能是这样的:
P4GO3}DG6G7BA5TSDTF5S}S.png
这个方法的问题在于,传递给map方法的Lambda为每个单词返回了一 个string[ ]。
因此,map返回的流实际上是Stream类型的。
你真正想要的是用Stream来表示一个字符流。
![9DC$IU539%]9)P]%CECP0B.png

可以用flatMap来解决这个问题。
1)尝试使用map和Arrays . stream()
首先,你需要一个字符流,而不是数组流。
有一个叫作Arrays. stream()的方法可以接受一个数组并产生一个流,例如:
A(AJFSAB(YNM~8H3V$7IFG1.png
把它用在前面的那个流水线里,看看会发生什么:
58AVIOD(8`2R2OH)96DAT8Y.png
当前的解决方案仍然搞不定。
这是因为,你现在得到的是一个流的列表(更准确地说是Stream>)。
的确,你先是把每个单词转换成一个字母数组,然后把每个数组变成了一个独立的流。
2)使用flatMap
你可以像下面这样使用flatMap来解决这个问题:
{5$Z2XE@DMW4}6EEF1_OREV.png
使用flatMap方法的效果是,各个数组并不是分别映射成一个流,而是映射成流的内容。
所有使用map (Arrays::stream)时生成的单个流都被合并起来,即扁平化为一个流。
IL1Y64BH4Z11LJ$RJ}7C(S3.png
flatmap方法让你把一个流中的每个值都换成另一个流,然后把所有的流连接起来成为一个流。
)R[BMB0}H[C)G6VJYCD$_DM.png](https://cdn.nlark.com/yuque/0/2021/png/12773302/1634048977244-d1ee660e-5091-4296-837a-7a94bcedcb82.png#clientId=u5de65d9f-76e8-4&from=drop&id=zwmvr&margin=%5Bobject%20Object%5D&name=%29R%5BBMB0%7DH%5BC%29G6VJYCD%24_DM.png&originHeight=404&originWidth=959&originalType=binary&ratio=1&size=119291&status=done&style=none&taskId=ua02fd30d-5a98-485b-b168-9c8cfd0d91d)<br />![I_F6(QGF)OGVN({58]T39$C.png