Java中map和flatMap的區(qū)別舉例詳解
一、map 和 flatMap 對(duì)應(yīng)的源碼
① 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 方法,都是對(duì)以流的形式數(shù)據(jù)的處理,返回值同樣都是流形式數(shù)據(jù)的泛型。本質(zhì)一樣,都是 map 操作,但是不同點(diǎn)在于,flatMap 操作會(huì)比 map 多一個(gè) flat 操作。
"flat"單詞本意有平的、扁平的含義,在源碼中,我們對(duì)于 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()操作的效果是對(duì)流的元素應(yīng)用一對(duì)多轉(zhuǎn)換,然后將生成的元素展平為新的流。而 map 方法的返回是:返回由將給定函數(shù)應(yīng)用于此流元素的結(jié)果組成的流。
說到這里可能還是會(huì)有些不太清晰,我們用代碼演示一下。
二、代碼演示
① 兩個(gè)類,一個(gè) Library 類,一個(gè) 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;
}② 測(cè)試類
public class StreamTest {
public static void main(String[] args) {
System.out.println("---------->存儲(chǔ)的圖書信息: ");
System.out.println(initInfo());
System.out.println("---------->測(cè)試map方法:");
testMap();
System.out.println("---------->測(cè)試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("三國(guó)演義", "羅貫中", 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));
}
}③ 測(cè)試結(jié)果

我們可以看到利用 flatMap 方法后,流中的數(shù)據(jù)被展平,消除了List<Book>的層級(jí)解構(gòu),但是 map 中的數(shù)據(jù)仍然存在層級(jí)結(jié)構(gòu)。
map 方法流的中間過程

flatMap 方法流的中間過程

可以清楚的看到,map 方法應(yīng)用后是存在層級(jí)結(jié)構(gòu)的,返回的流是List<Book>組成的流,而 flatMap 中消除了List<Book>的層級(jí)結(jié)構(gòu),返回的流是 Book 組成的流。
附:相關(guān)問題
那我要是這種3層數(shù)據(jù)結(jié)構(gòu)呢?,怎么把它們展開轉(zhuǎn)化為大寫字母?
[ [ ['a', 'b'], ['c', 'd'] ], [ ['e', 'f'], ['g', 'h'] ] ] ==>
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
很簡(jiǎn)單,先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()
}
}
}總結(jié):
當(dāng)我們需要將具有層級(jí)結(jié)構(gòu)的數(shù)據(jù)展平時(shí),也就是將多層數(shù)據(jù)轉(zhuǎn)換為單層數(shù)據(jù)操作時(shí),我們可以使用 flatMap 方法。如果我們只是簡(jiǎn)單的對(duì)流中的數(shù)據(jù)計(jì)算或者轉(zhuǎn)換時(shí),可以使用 map 方法。
舉例:
① 使用 flatMap:[a,b,c,d,[e,f [g,h,i]]] 轉(zhuǎn)換為 [a,b,c,d,e,f,g,h,i]
② 使用 map: [1,2,3,4,5,6] 轉(zhuǎn)換為 [11,12,13,14,15,16]
③ 使用 map: [a,b,c] 轉(zhuǎn)換為 [A,B,C]
到此這篇關(guān)于Java中map和flatMap的區(qū)別的文章就介紹到這了,更多相關(guān)Java map和flatMap區(qū)別內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java如何實(shí)現(xiàn)獲取客戶端ip地址的示例代碼
本文主要介紹了java如何實(shí)現(xiàn)獲取客戶端ip地址,主要包括java獲取客戶端ip地址工具類使用實(shí)例、應(yīng)用技巧,文中通過示例代碼介紹的非常詳細(xì),感興趣的小伙伴們可以參考一下2022-04-04
在SpringBoot中使用MongoDB的簡(jiǎn)單場(chǎng)景案例
MongoDB 是一種非關(guān)系型數(shù)據(jù)庫,也被稱為 NoSQL 數(shù)據(jù)庫,它主要以文檔的形式存儲(chǔ)數(shù)據(jù),本文給大家介紹了在SpringBoot中使用MongoDB的簡(jiǎn)單場(chǎng)景案例,并通過代碼示例講解的非常詳細(xì),需要的朋友可以參考下2024-09-09
基于python locust庫實(shí)現(xiàn)性能測(cè)試
這篇文章主要介紹了基于python locust庫實(shí)現(xiàn)性能測(cè)試,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05
SpringBoot 多線程事務(wù)回滾的實(shí)現(xiàn)
本文是基于springboot的@Async注解開啟多線程,并通過自定義注解和AOP實(shí)現(xiàn)的多線程事務(wù),避免繁瑣的手動(dòng)提交/回滾事務(wù),感興趣的可以了解一下2024-02-02

