君子成人之美,不成人之恶。小人反是。——《论语》
在Stream中有这么一个函数

它和map不一样的是,map你输入多少个,输出就是多少个
例如我要生成一个集合,装着26个小写字母和26个大写字母
用flatMap可以一行实现
1 | |

马上这时候就有人跳出来说,我不用flatMap还不是可以!!!不信你看
1 | |
。。。我只能说,我这篇博客是写flatMap,所以不要杠,我知道Stream.concat可以换成Stream.of
而且,你下面这种方式生成58个元素,其中浪费了6个元素
而我上面的方式只用26个元素就生成了54个元素
哪种方式的入参代价更小,明白了吧
那么这个flatMap如何使用?
再来看个例子:
九九乘法表都会吧
我们用flatMap一行写一个
1 | |

看懂了吗?
还看不懂???
那我们来读源码
1 | |
可以看到flatMap里就一个参数,Function
而关键就在于Function的两个泛型,注意不是T和R,而是? super T和? extends Stream<? extends R>
然后现在你可能有点懵,这两个泛型干嘛的
第一个泛型? super T你甚至可以忽略掉? super去看,直接把他认为是泛型T,而这个泛型T,就是我们原来的元素
简单来说,它就是你的入参,就是你的集合里的每一个元素
就是.flatMap(i -> Stream.concat(Stream.of(i), Stream.of(i).map(String::toUpperCase)))中的i
第二个泛型? extends Stream<? extends R>同理,你先忽略掉? extends,表示你的返回值需要Stream<R>类型
这个R可以和T一样,也可以不一样
例如我这里就是一样的,都是String类型,我使用Steam.of以及Stream.concat函数去将我们的元素转换成Stream再返回
就是.flatMap(i -> Stream.concat(Stream.of(i), Stream.of(i).map(String::toUpperCase)))中箭头右边部分
举个开发中遇到的场景
假设用户类,其中部分用户有个父账户id,对应父账户,使用的同一张表
你现在拿到了一个包含这些用户的list,需要把用户id和父账户id放到一个list里面去进行in查询
就可以这么写
1 | |
打印出来结果

Optional中也有flatMap函数,这个我们之后再讲