扫码阅读
手机扫码阅读

Java Stream中map和flatMap方法

65 2024-04-17

最近看到一篇讲stream语法的文章,学习Javamap()flatMap()方法之间的区别。

虽然看起来这两种方法都做同样的事情,都是做的映射操作,但实际上差之毫厘谬以千里。

通过演示Demo中的代码可以了解map()flatMap()的具体功能差异。

  • 首先来一段简单的stream语法foreach方法的用法

演示Demo:

 List funs = Arrays.asList("F", "U", "N");
        funs.stream().forEach(x -> output(x)); 

控制台输出:

INFO-> 当前用户:fv,IP:10.60.192.21,工作目录:/Users/fv/Documents/workspace/fun/,系统编码格式:UTF-8,系统Mac OS X版本:10.15.7 F
U
N
Process finished with exit code 0 

map方法

map()是一个中间操作,这意味着它返回Stream对象。

  • 先来一个简单

演示Demo:

 List funs = Arrays.asList("F", "U", "N");
        funs.stream().map(x->x+"001").forEach(x->output(x)); 

控制台输出:

INFO-> 当前用户:fv,IP:10.60.192.21,工作目录:/Users/fv/Documents/workspace/fun/,系统编码格式:UTF-8,系统Mac OS X版本:10.15.7 INFO-> f INFO-> u INFO-> n INFO-> F001 INFO-> U001 INFO-> N001 java.util.stream.ReferencePipeline$3@27ae2fd0
java.util.stream.ReferencePipeline$3@29176cc1
Process finished with exit code 0 
  • 再来一个复杂的

演示Demo:

 List fun1 = Arrays.asList("one", "two", "three");
        List fun2 = Arrays.asList("four", "five", "six");
        List> nestedList = Arrays.asList(fun1, fun2);
        nestedList.stream().map(x -> { return x.stream().map(a -> a.toUpperCase());
        }).forEach(x -> output(x)); 

控制台输出:

INFO-> 当前用户:fv,IP:10.60.192.21,工作目录:/Users/fv/Documents/workspace/fun/,系统编码格式:UTF-8,系统Mac OS X版本:10.15.7 INFO-> java.util.stream.ReferencePipeline$3@45018215 INFO-> java.util.stream.ReferencePipeline$3@30b7c004 

显然,在最后一步输出的时候,x是一个stream的对象,而不是一个list对象。

当我们尝试从List>获取值进行操作时,map()无法如预期一样工作,需要进行修改才能从嵌套的List>对象获取字符串值。

如下:

 List fun1 = Arrays.asList("one", "two", "three");
        List fun2 = Arrays.asList("four", "five", "six");
        List> nestedList = Arrays.asList(fun1, fun2);
        nestedList.stream().map(x -> { return x.stream().map(a -> a.toUpperCase());
        }).forEach(x ->x.forEach(a->output(a))); 

控制台输出:

INFO-> 当前用户:fv,IP:10.60.192.21,工作目录:/Users/fv/Documents/workspace/fun/,系统编码格式:UTF-8,系统Mac OS X版本:10.15.7 INFO-> ONE INFO-> TWO INFO-> THREE INFO-> FOUR INFO-> FIVE INFO-> SIX Process finished with exit code 0 

flatMap方法

让我们在上述代码中将map()更改为flatMap(),然后查看输出。

  • 先来一个简单

演示Demo:

 List fun1 = Arrays.asList("one", "two", "three");
        List fun2 = Arrays.asList("four", "five", "six");
        List> nestedList = Arrays.asList(fun1, fun2);
        nestedList.stream().flatMap(x -> x.stream()).map(x->x.toUpperCase()).forEach(x -> output(x)); 

控制台输出:

INFO-> 当前用户:fv,IP:10.60.192.21,工作目录:/Users/fv/Documents/workspace/fun/,系统编码格式:UTF-8,系统Mac OS X版本:10.15.7 INFO-> ONE INFO-> TWO INFO-> THREE INFO-> FOUR INFO-> FIVE INFO-> SIX Process finished with exit code 0 

相当于在.flatMap(x -> x.stream())这个时候我们把x.stream()返回的stream对象合并成了一个新的stream对象。这一点在Stream类的方法注释中找到了印证。

 /**
  ·····
     * @return the new stream
     */  Stream flatMap(Functionsuper T, ? extends Stream> mapper); 

Java 8 map()与flatMap()

map()flatMap()方法都可以应用于StreamOptional对象。并且都返回StreamOptional 对象。区别在于map()操作为每个输入值生成一个输出值,而flatMap()操作为每个输入值生成任意数量(零个或多个)的输出值。

flatMap()中,每个输入始终是一个集合,可以是ListSetMap

map()操作采用一个方法,该方法针对输入流中的每个值调用,并生成一个结果值,该结果值返回至stream

flatMap()操作采用的功能在概念上消耗一个集合对象并产生任意数量的值。但是在Java中方法返回任意数目的值很麻烦,因为方法只能返回void或一个对象。

演示Demo:

 List fun1 = Arrays.asList("one", "two", "three");
        List fun2 = Arrays.asList("four", "five", "six");
        Stream.of(fun1,fun2).flatMap(List::stream).forEach(Output::output); 

控制台输出:

INFO-> 当前用户:fv,IP:10.60.192.21,工作目录:/Users/fv/Documents/workspace/fun/,系统编码格式:UTF-8,系统Mac OS X版本:10.15.7 INFO-> one INFO-> two INFO-> three INFO-> four INFO-> five INFO-> six Process finished with exit code 0 
原文链接: https://mp.weixin.qq.com/s?__biz=MzU4MTE2NDEyMQ==&mid=2247488078&idx=1&sn=2d0cffbc545a8e07c670411cdc134df7