参考文献:
Java Stream中map和flatMap方法
map 方法
map 是一个中间操作,这意味着它返回 Stream 对象。
List<String> funs = Arrays.asList("F", "U", "N");
funs.stream().map(x -> x + "001").forEach(System.out::println);
F001
U001
N001
看个复杂点的
List<String> fun1 = Arrays.asList("one", "two", "three");
List<String> fun2 = Arrays.asList("four", "five", "six");
List<List<String>> nestedList = Arrays.asList(fun1, fun2);
nestedList.stream()
.map(x -> x.stream().map(String::toUpperCase))
.forEach(System.out::println);
java.util.stream.ReferencePipeline$3@7b23ec81
java.util.stream.ReferencePipeline$3@6acbcfc0
显然,在最后一步输出的时候,x 是一个 stream 的对象,而不是一个 list 对象。
当我们尝试从List<List<String>>
获取值进行操作时,map 无法如预期一样工作,需要进行修改才能从嵌套的List<List<String>>
对象获取字符串值。
List<String> fun1 = Arrays.asList("one", "two", "three");
List<String> fun2 = Arrays.asList("four", "five", "six");
List<List<String>> nestedList = Arrays.asList(fun1, fun2);
nestedList.stream().map(x -> x.stream().map(String::toUpperCase))
.forEach(x -> x.forEach(System.out::println));
ONE
TWO
THREE
FOUR
FIVE
SIX
flatMap
让我们在上述代码中将 map 更改为 flatMap,然后查看输出。
List<String> fun1 = Arrays.asList("one", "two", "three");
List<String> fun2 = Arrays.asList("four", "five", "six");
List<List<String>> nestedList = Arrays.asList(fun1, fun2);
nestedList.stream().flatMap(Collection::stream)
.map(String::toUpperCase)
.forEach(System.out::println);
ONE
TWO
THREE
FOUR
FIVE
SIX
相当于在 .flatMap(x -> x.stream())
这个时候我们把x.stream()
返回的 stream 对象合并成了一个新的 stream 对象
区别
map 和 flatMap 方法都可以应用于 Stream<T>
和 Optional<T>
对象。并且都返回Stream<R>
或 Optional <U>
对象。区别在于 map 操作为每个输入值生成一个输出值,而 flatMap 操作为每个输入值生成任意数量(零个或多个)的输出值。
在 flatMap 中,每个输入始终是一个集合,可以是 List 或 Set 或 Map,扁平化处理,输出一个汇总值。
map 操作采用一个方法,该方法针对输入流中的每个值调用,并生成一个结果值,该结果值返回至stream。
flatMap 操作采用的功能在概念上消耗一个集合对象并产生任意数量的值。
List<String> fun1 = Arrays.asList("one", "two", "three");
List<String> fun2 = Arrays.asList("four", "five", "six");
Stream.of(fun1, fun2).flatMap(List::stream)
.forEach(System.out::println);
one
two
three
four
five
six