flatMap

2021-05-31

java

君子成人之美,不成人之恶。小人反是。——《论语》

Stream中有这么一个函数

image-20210531232225786

它和map不一样的是,map你输入多少个,输出就是多少个

例如我要生成一个集合,装着26个小写字母和26个大写字母

flatMap可以一行实现

1
2
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());
System.out.println(abc);

image-20210531233743054

马上这时候就有人跳出来说,我不用flatMap还不是可以!!!不信你看

1
2
List<Character> ab = Stream.iterate('A', i -> ++i).limit(58).filter(i -> i < 91 || i > 96).collect(Collectors.toList());
System.out.println(ab);

。。。我只能说,我这篇博客是写flatMap,所以不要杠,我知道Stream.concat可以换成Stream.of

而且,你下面这种方式生成58个元素,其中浪费了6个元素

而我上面的方式只用26个元素就生成了54个元素

哪种方式的入参代价更小,明白了吧

那么这个flatMap如何使用?

再来看个例子:

九九乘法表都会吧

我们用flatMap一行写一个

1
2
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());
nineNine.forEach(System.out::println);

image-20210531233930490

看懂了吗?

还看不懂???

那我们来读源码

1
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);

可以看到flatMap里就一个参数,Function

而关键就在于Function的两个泛型,注意不是TR,而是? 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
2
3
4
List<User> userList = new ArrayList<>();
userList.add(User.builder().id("用户id").parentId("父id").build());
List<String> userIds = userList.parallelStream().flatMap(u -> Stream.of(u.getId(), u.getParentId())).collect(Collectors.toList());
System.out.println(userIds);

打印出来结果

image-20210531235346955

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