場景設定
假設有一個包含句子的 RDD:
scala
val rdd = sc.parallelize(List("Hello World", "Hi Spark"))
目標是:將每個句子拆分成單詞。
1. 用?map
?的效果
代碼示例
scala
val resultMap = rdd.map(sentence => sentence.split(" "))
resultMap.collect()
輸出結果
scala
Array[Array[String]] = Array(Array("Hello", "World"), Array("Hi", "Spark"))
發生了什么?
-
map
?一對一轉換:-
輸入一個句子?
"Hello World"
?→ 輸出一個單詞數組?Array("Hello", "World")
-
輸入一個句子?
"Hi Spark"
?→ 輸出一個單詞數組?Array("Hi", "Spark")
-
-
結果結構:嵌套的數組(每個元素還是數組)。
2. 用?flatMap
?的效果
代碼示例
scala
val resultFlatMap = rdd.flatMap(sentence => sentence.split(" "))
resultFlatMap.collect()
輸出結果
scala
Array[String] = Array("Hello", "World", "Hi", "Spark")
發生了什么?
-
flatMap
?一對多轉換:-
輸入一個句子?
"Hello World"
?→ 拆分成兩個單詞?"Hello"
?和?"World"
-
輸入一個句子?
"Hi Spark"
?→ 拆分成兩個單詞?"Hi"
?和?"Spark"
-
-
結果結構:扁平化的數組(所有單詞在一個數組中)。
核心區別總結
操作 | 輸入 → 輸出關系 | 結果結構 | 適用場景 |
---|---|---|---|
map | 1個輸入 → 1個輸出(類型可變) | 保持嵌套結構 | 簡單轉換(如類型轉換、數值計算) |
flatMap | 1個輸入 → 多個輸出(自動展平) | 扁平化單層結構 | 拆分數據(如分詞、展開嵌套結構) |
圖解對比
原始數據: List("Hello World", "Hi Spark") ↓ ↓
map 處理: Array("Hello", "World") Array("Hi", "Spark") → 結果:嵌套數組 | | | |
flatMap 處理: "Hello" "World" "Hi" "Spark" → 結果:扁平數組
什么時候用?map
?
-
保留結構:比如將字符串轉大寫、對數字做運算。
scala
val numbers = sc.parallelize(List(1, 2, 3)) val doubled = numbers.map(_ * 2) // 輸出:List(2, 4, 6)
什么時候用?flatMap
?
-
拆分或展開數據:比如將句子拆成單詞、展開嵌套集合。
scala
val nestedList = sc.parallelize(List(List(1, 2), List(3, 4))) val flattened = nestedList.flatMap(identity) // 輸出:List(1, 2, 3, 4)
高級用法
鏈式調用示例
scala
// 同時使用 map 和 flatMap
val sentences = sc.parallelize(List("Hello World", "Hi Spark"))// 步驟分解:
// 1. 用 map 將句子轉大寫
// 2. 用 flatMap 拆分單詞
val result = sentences.map(_.toUpperCase).flatMap(_.split(" "))result.collect() // 輸出:Array("HELLO", "WORLD", "HI", "SPARK")
一句總結
map
?是變形,flatMap
?是拆開壓平!
需要保持結構用?map
,需要展開數據用?flatMap
!