Java中map和flatMap的区别举例详解
作者:LOVE️YOU
一、map 和 flatMap 对应的源码
① map方法
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
② flatMap方法
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
可以看到,不论是 map 还是 flatMap 方法,都是对以流的形式数据的处理,返回值同样都是流形式数据的泛型。本质一样,都是 map 操作,但是不同点在于,flatMap 操作会比 map 多一个 flat 操作。
"flat"单词本意有平的、扁平的含义,在源码中,我们对于 flatMap 方法中 API Note 有这样一句话:"The flatMap() operation has the effect of applying a one-to-many transformation to the elements of the stream, and then flattening the resulting elements into a new stream.",含义是:flatMap()操作的效果是对流的元素应用一对多转换,然后将生成的元素展平为新的流。而 map 方法的返回是:返回由将给定函数应用于此流元素的结果组成的流。
说到这里可能还是会有些不太清晰,我们用代码演示一下。
二、代码演示
① 两个类,一个 Library 类,一个 Book 类
@Data @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode public class Library { private String name; private List<Book> book; }
@Data @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode public class Book { private String name; private String author; private Integer price; }
② 测试类
public class StreamTest { public static void main(String[] args) { System.out.println("---------->存储的图书信息: "); System.out.println(initInfo()); System.out.println("---------->测试map方法:"); testMap(); System.out.println("---------->测试flatMap方法:"); testFlatMap(); } private static void testMap() { initInfo().stream() .map(library -> library.getBook()) .forEach(book -> System.out.println(book)); } private static void testFlatMap() { initInfo().stream() .flatMap(library -> library.getBook().stream()) .forEach(book -> System.out.println(book)); } public static List<Library> initInfo() { Library library1 = new Library("新华图书", null); Library library2 = new Library("大家图书", null); Library library3 = new Library("瀚海图书", null); Book book1 = new Book("西游记", "吴承恩", 49); Book book2 = new Book("水浒传", "施耐庵", 57); Book book3 = new Book("三国演义", "罗贯中", 52); Book book4 = new Book("朝花夕拾", "鲁迅", 30); List<Book> library1Book = new ArrayList<>(); List<Book> library2Book = new ArrayList<>(); List<Book> library3Book = new ArrayList<>(); library1Book.add(book1); library1Book.add(book2); library2Book.add(book2); library2Book.add(book3); library3Book.add(book3); library3Book.add(book4); library1.setBook(library1Book); library2.setBook(library2Book); library3.setBook(library3Book); return new ArrayList<>(Arrays.asList(library1, library2, library3)); } }
③ 测试结果
我们可以看到利用 flatMap 方法后,流中的数据被展平,消除了List<Book>的层级解构,但是 map 中的数据仍然存在层级结构。
map 方法流的中间过程
flatMap 方法流的中间过程
可以清楚的看到,map 方法应用后是存在层级结构的,返回的流是List<Book>组成的流,而 flatMap 中消除了List<Book>的层级结构,返回的流是 Book 组成的流。
附:相关问题
那我要是这种3层数据结构呢?,怎么把它们展开转化为大写字母?
[ [ ['a', 'b'], ['c', 'd'] ], [ ['e', 'f'], ['g', 'h'] ] ] ==>
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
很简单,先flatMap展开两层,然后map就好了。
val orgList: List<List<List<Char>>> = listOf( listOf( listOf('a', 'b'), listOf('c', 'd') ), listOf( listOf('e', 'f'), listOf('g', 'h') ) ) val transList = orgList.flatMap { outterList -> outterList.flatMap { innerList -> innerList.map { charStr -> charStr.uppercaseChar() } } }
总结:
当我们需要将具有层级结构的数据展平时,也就是将多层数据转换为单层数据操作时,我们可以使用 flatMap 方法。如果我们只是简单的对流中的数据计算或者转换时,可以使用 map 方法。
举例:
① 使用 flatMap:[a,b,c,d,[e,f [g,h,i]]] 转换为 [a,b,c,d,e,f,g,h,i]
② 使用 map: [1,2,3,4,5,6] 转换为 [11,12,13,14,15,16]
③ 使用 map: [a,b,c] 转换为 [A,B,C]
到此这篇关于Java中map和flatMap的区别的文章就介绍到这了,更多相关Java map和flatMap区别内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!