java8中 map和flatmap的共同點和區別,以及兩者的例項解析
https://blog.csdn.net/zhuwukai/article/details/82888316
在函式式語言中,函式作為一等公民,可以在任何地方定義,在函式內或函式外,可以作為函式的引數和返回值,可以對函式進行組合。由於指令式程式設計語言也可以通過類似函式指標的方式來實現高階函式,函式式的最主要的好處主要是不可變性帶來的。沒有可變的狀態,函式就是引用透明(Referential transparency)的和沒有副作用(No Side Effect)。
任何一種函式式語言中,都有map函式與faltMap這兩個函式,比如python雖然不是純函式式語言,也有這兩個函式。再比如在jdk1.8之後,也加入了Lambda表示式,自然也支援map函式。
上海尚學堂java培訓在這文章中就著重介紹下Map和faltMap
一、map和faltMap的共同點和區別
1、共同點
- 都是依賴FuncX(入參,返回值)進行轉換(將一個型別依據程式邏輯轉換成另一種型別,根據入參和返回值)
- 都能在轉換後直接被subscribe
2、區別
- map返回的是結果集,flatmap返回的是包含結果集的Observable(返回結果不同)
- map被訂閱時每傳遞一個事件執行一次onNext方法,flatmap多用於多對多,一對多,再被轉化為多個時,一般利用from/just進行一一分發,被訂閱時將所有資料傳遞完畢彙總到一個Observable然後一一執行onNext方法(執行順序不同)>>>>(如單純用於一對一轉換則和map相同)
- map只能單一轉換,單一隻的是隻能一對一進行轉換,指一個物件可以轉化為另一個物件但是不能轉換成物件陣列(map返回結果集不能直接使用from/just再次進行事件分發,一旦轉換成物件陣列的話,再處理集合/陣列的結果時需要利用for一一遍歷取出,而使用RxJava就是為了剔除這樣的巢狀結構,使得整體的邏輯性更強。)
- flatmap既可以單一轉換也可以一對多/多對多轉換,flatmap要求返回Observable,因此可以再內部進行from/just的再次事件分發,一一取出單一物件(轉換物件的能力不同)
二、例項
假如我們有這樣一個需求給定單詞列表["Hello","World"],你想要返回列表["H","e","l", "o","W","r","d"],
words.stream() .map(word -> word.split("")) .distinct() .collect(toList());
這個方法的問題在於,傳遞給map方法的Lambda為每個單詞返回了一個String[](String
列表)。因此, map 返回的流實際上是Stream型別的。你真正想要的是用
Stream來表示一個字元流。因此,這是行不通的。
以下是我對這個問題的解法和分步寫法,希望能對你有幫助:
String ss = "Hello";
String[] aa = ss.split("");
String[] bb = {"H", "e", "l", "l", "o"};
String[] strings = {"Hello", "World"};
//Arrays.stream接收一個數組返回一個流
List<Stream<String>> streamList = Arrays.asList(strings).stream().
map(str -> str.split("")).
map(str -> Arrays.stream(str)).
collect(Collectors.toList());
//分步寫(map)
Stream<String[]> stream = Arrays.asList(strings).stream().
map(str -> str.split(""));
Stream<Stream<String>> streamStream = stream.map(strings1 -> Arrays.stream(strings1));
List<Stream<String>> streamList1 = streamStream.collect(Collectors.toList());
List<String> stringList = Arrays.asList(strings).stream().
map(str -> str.split("")).
flatMap(str -> Arrays.stream(str))
.collect(Collectors.toList());
//分步寫(流只能消費一次)(flatMap)
Stream<String[]> stream1 = Arrays.asList(strings).stream().
map(str -> str.split(""));
Stream<String> stringStream = stream1.flatMap(strings1 -> Arrays.stream(strings1));
List<String> stringList1 = stringStream.collect(Collectors.toList()); 對flatMap的說明:這個在這裡的主要作用是對流進行扁平化
三、最後總結
現在簡單說說scala中這兩個函式的用法。有一種觀點認為將map和flatMap說成Scala函式機制的核心都不為過分,其實是有一定道理的。因為實際中我們使用最多的場景就是對資料進行map操作或者flatMap操作。
map函式的用法,顧名思義,將一個函式傳入map中,然後利用傳入的這個函式,將集合中的每個元素處理,並將處理後的結果返回。而flatMap與map唯一不一樣的地方就是傳入的函式在處理完後返回值必須是List,其實這也不難理解,既然是flatMap,那除了map以外必然還有flat的操作,所以需要返回值是List才能執行flat這一步。
這樣寫就行了
Stream.of(new String[] {"Hello", "World"}).flatMap(str -> Arrays.stream(str.split(""))).distinct()
.collect(Collectors.toList())