<R> Stream<R> flatMap(Function<? super T,? extends Stream<? extends R>> mapper)
这个方法在使用的时候需要注意的一点就是其返回值是一个stream。
这个方法的应用场景基本上就是对集合中存放集合这类数据进行处理。例如,有一个集合其中存放的数据是String类型数据的集合:List<List<String>>(List<String>,…);假如我们要把所有集合中的String取出来放到一个集合中怎么操作?下面看一个例子:
void stream_flatMap2() {
List<List<String>> list = List.of(List.of("a","b","c","d"), List.of("1","2","3","4"), List.of("one","two","three"));
list.stream().forEach(System.out::print);
System.out.println();
Stream<String> stream = list.stream().flatMap(onelist -> onelist.stream());
stream.forEach(System.out::print);
}
运行结果:
[a, b, c, d][1, 2, 3, 4][one, two, three]
abcd1234onetwothree
第一个输出是把list按照原始数据结构给打印出来;因为我们只对外层List创建流,因此使用此流存放的元素都是一个个List结构的数据,直接打印出来就是上面的结果。
第二个输出我们先对外层list创建流,然后从流中依次取元素list再创建流,最后把内层的所有的流都concat起来,形成一个流输出,打印结果就是一个字符串。
关于第一个输出我们可以再修改一下,可以得出和第二个输出一样的结果,看如下代码:
//list.stream().forEach(System.out::print);
list.stream().forEach(onelist -> onelist.stream().forEach(System.out::print));
把注释掉的代码修改为其下面那行代码,其输出结果和上面例子第二个输出一样。
下面再看一个例子,在这个例子中我们使用reduce方法遍历流中元素,然后再使用concat方法把这些元素连接起来最后放到一个stream中。
Optional<List<String>> list1 = list.stream().reduce((a,b) -> Stream.concat(a.stream(), b.stream()).collect(Collectors.toList()));
list1.get().stream().forEach(System.out::print);
运行结果:abcd1234onetwothree
可以看到这个结果和上面两个例子结果一样,达到了我们的目的。
从上面代码可以看出stream对集合类型的数据的处理能力是何等的强大。一行代码可以解决好几个需求。