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

它和map不一样的是,map你输入多少个,输出就是多少个
例如我要生成一个集合,装着26个小写字母和26个大写字母
用flatMap可以一行实现
| List<String> abc = Stream.iterate('a', i -> ++i).map(String::valueOf).limit(26).flatMap(i -> Stream.concat(Stream.of(i), Stream.of(i).map(String::toUpperCase))).sorted().collect(Collectors.toList()); | 

马上这时候就有人跳出来说,我不用flatMap还不是可以!!!不信你看
| List<Character> ab = Stream.iterate('A', i -> ++i).limit(58).filter(i -> i < 91 || i > 96).collect(Collectors.toList()); | 
。。。我只能说,我这篇博客是写flatMap,所以不要杠,我知道Stream.concat可以换成Stream.of
而且,你下面这种方式生成58个元素,其中浪费了6个元素
而我上面的方式只用26个元素就生成了54个元素
哪种方式的入参代价更小,明白了吧
那么这个flatMap如何使用?
再来看个例子:
九九乘法表都会吧
我们用flatMap一行写一个
| List<String> nineNine = Stream.iterate(1, i -> ++i).flatMap(i -> Stream.iterate(i, in -> ++in).map(in -> i + "*" + in + "=" + i * in).limit(10 - i)).limit(45).collect(Collectors.toList()); | 

看懂了吗?
还看不懂???
那我们来读源码
| <R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper); | 
可以看到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查询
就可以这么写
| List<User> userList = new ArrayList<>(); | 
打印出来结果

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




