在Java 8中,Stream.map()和Stream.flatMap()方法之间有什么区别?
当前回答
我想举两个例子来说明更实际的观点: 第一个使用地图的例子:
@Test
public void convertStringToUpperCaseStreams() {
List<String> collected = Stream.of("a", "b", "hello") // Stream of String
.map(String::toUpperCase) // Returns a stream consisting of the results of applying the given function to the elements of this stream.
.collect(Collectors.toList());
assertEquals(asList("A", "B", "HELLO"), collected);
}
在第一个例子中没有什么特别的,一个函数被应用来返回大写的String。
第二个使用flatMap的例子:
@Test
public void testflatMap() throws Exception {
List<Integer> together = Stream.of(asList(1, 2), asList(3, 4)) // Stream of List<Integer>
.flatMap(List::stream)
.map(integer -> integer + 1)
.collect(Collectors.toList());
assertEquals(asList(2, 3, 4, 5), together);
}
在第二个例子中,传递了一个List流。它不是一个整数流! 如果必须使用转换函数(通过map),则首先必须将流平展为其他类型的流(整数流)。 如果flatMap被移除,则返回以下错误:对于参数类型List, int,操作符+未定义。 不可能在整数列表上应用+ 1 !
其他回答
我想举两个例子来说明更实际的观点: 第一个使用地图的例子:
@Test
public void convertStringToUpperCaseStreams() {
List<String> collected = Stream.of("a", "b", "hello") // Stream of String
.map(String::toUpperCase) // Returns a stream consisting of the results of applying the given function to the elements of this stream.
.collect(Collectors.toList());
assertEquals(asList("A", "B", "HELLO"), collected);
}
在第一个例子中没有什么特别的,一个函数被应用来返回大写的String。
第二个使用flatMap的例子:
@Test
public void testflatMap() throws Exception {
List<Integer> together = Stream.of(asList(1, 2), asList(3, 4)) // Stream of List<Integer>
.flatMap(List::stream)
.map(integer -> integer + 1)
.collect(Collectors.toList());
assertEquals(asList(2, 3, 4, 5), together);
}
在第二个例子中,传递了一个List流。它不是一个整数流! 如果必须使用转换函数(通过map),则首先必须将流平展为其他类型的流(整数流)。 如果flatMap被移除,则返回以下错误:对于参数类型List, int,操作符+未定义。 不可能在整数列表上应用+ 1 !
对于Map,我们有一个元素列表和一个(函数,动作)f,这样:
[a,b,c] f(x) => [f(a),f(b),f(c)]
对于平面映射,我们有一个元素列表,我们有一个(function,action) f,我们希望结果是扁平的:
[[a,b],[c,d,e]] f(x) =>[f(a),f(b),f(c),f(d),f(e)]
这对初学者来说是很困惑的。基本的区别是map为列表中的每个条目发出一个项,而flatMap基本上是一个map + flatten操作。更清楚地说,当你需要多个值时使用flatMap,例如当你期望一个循环返回数组时,flatMap在这种情况下非常有用。
我写了一篇关于这方面的博客,你可以在这里查看。
通过阅读所有的信息,简单的理解方法是:
如果你有一个元素的平面列表,请使用map: [0,1,2,3,4,5] 如果你有一个元素的列表,请使用flatMap:[[1,3,5],[2,4,6]]。这意味着,在映射操作应用于每个元素之前,您的列表需要被平铺
如果您认为map()是一个迭代(一级for循环),那么flatmap()是一个两级迭代(类似于嵌套的for循环)。(输入每个迭代元素foo,然后执行foo. getbarlist()并再次迭代该barList)
Map():获取一个流,对每个元素做一些事情,收集每个进程的单个结果,输出另一个流。“做一些函数”的定义是隐含的。如果任何元素的处理结果为null,则使用null来组成最终流。因此,结果流中的元素数量将等于输入流的数量。
Flatmap():获取元素/流流和函数(显式定义)的流,将函数应用到每个流的每个元素,并将所有中间结果流收集为更大的流(“扁平化”)。如果任何元素的处理结果为null,则为“扁平化”的最后一步提供空流。如果输入是几个流,则结果流中的元素数量是所有输入中所有参与元素的总和。
推荐文章
- 字符串是不可变的。到底是什么意思呢?
- Java GUI框架。选择什么?Swing, SWT, AWT, SwingX, JGoodies, JavaFX, Apache Pivot?
- 在Java中从字符串中提取数字
- 套接字的连接超时和读超时之间的区别是什么?
- Java整数到字节数组
- 如何设置Windows环境下Java的环境变量
- Java Swing revalidate() vs repaint()
- Java中文件中的行数
- 指定的子节点已经有一个父节点。你必须先在子对象的父对象上调用removeView() (Android)
- 对于一个布尔字段,它的getter/setter的命名约定是什么?
- 如何获得当前屏幕方向?
- 如何在Android中渲染PDF文件
- 如何计算一个元素在列表中出现的次数
- c++中类似于java的instanceof
- 我如何解决错误“minCompileSdk(31)指定在一个依赖的AAR元数据”在本机Java或Kotlin?