为什么我不能在Spark的mapPartitions中使用foreach

时间:2018-07-30 06:50:54

标签: scala apache-spark rdd

我使用SparkContext使用2个分区创建了一个数组,我也尝试使用mapPartition处理元素,但是当我这样编写代码时,我遇到了一个非常奇怪的错误:

val masterURL = "local[*]"

val conf = new SparkConf().setAppName("KMeans Test").setMaster(masterURL)
val sc = new SparkContext(conf)
sc.setLogLevel("WARN")

val data = sc.textFile("file:/d:/data/kmeans_data.txt")
val parsedData = data.mapPartitions(partition => parseData(partition)).cache()

parsedData.mapPartitions(points =>
  points.map(point =>
    println(point)
  )
)

它没有错误,但是,当我将map替换为foreach时,它提示一个错误:

parsedData.mapPartitions(points =>
  points.foreach(point =>
   println(point)
  )
)

错误如下:

  

类型不匹配,预期:(​​Iterator [Vector])=> Iterator [NotInferedU],   实际的:(Iterator [Vector])=> Unit类型的Unit表达式不   符合预期的Iterator类型[U _]

此外,第一个代码片段也无法在控制台面板中打印任何内容,为什么?

2 个答案:

答案 0 :(得分:3)

由于foreach方法返回Unit类型,因此您收到此错误。 mapPartitions方法无法返回该类型。尝试返回您收到的相同迭代器:

parsedData.mapPartitions(points =>
  points.foreach(point =>
   println(point)
  )
  points
)

应该可以。

  

此外,第一个代码片段也无法在控制台面板中打印任何内容,为什么?

因为map函数在调用动作之前不会执行任何操作(例如collectforeach)。

答案 1 :(得分:0)

mapPartitions期望一个函数返回一个新的分区迭代器(Iterator[Vector] => Iterator[NotInferedU]),它将一个迭代器映射到另一个迭代器。 通过使用foreach,您可以返回与预期返回类型不同的void(Scala中的Unit)。

要打印RDD内容,可以使用foreachPartition代替mapPartitions

parsedData.foreachPartition(points =>
  points.foreach(point =>
    println(point)
  )
)