Scala:无法将RDD中的值分配给ArrayBuffer

时间:2017-05-21 07:27:38

标签: scala rdd

以下是我的代码:

class Data(val x:Double=0.0,val y:Double=0.0) {
  var cluster = 0;
}

var dataList = new ArrayBuffer[Data]()

val data = sc.textFile("Path").map(line => line.split(",")).map(userRecord => (userRecord(3), userRecord(4)))

data.foreach(a => dataList += new Data(a._1.toDouble, a._2.toDouble))

当我这样做的时候     dataList.size 我输出为0 但是数据中有4k以上的记录。

现在我尝试使用take

data.take(10).foreach(a => dataList += new Data(a._1.toDouble, a._2.toDouble))

现在我获得了dataList中的数据。但我希望我的整个数据都在dataList中。

请帮忙。

2 个答案:

答案 0 :(得分:0)

问题是foreach中的代码在分布式工作程序上运行,而不是您检查dataList.length的主线程。使用Rdd.collect()获取它。

val dataList = data
       .take(10)
       .map(a => new Data(a._1.toDouble, a._2.toDouble))
       .collect()

答案 1 :(得分:0)

问题与您的代码执行位置有关。在转换中进行的每个操作,即mapflatMapreduce等,都不会在主线程中执行(或在< em> driver node),但在 worker 节点中。这些节点在不同于驱动程序节点的线程(或主机)中运行。

未存储在RDD内并且在工作节点中使用的每个对象仅存在于工作器内存空间中。然后,只需在每个worker中新创建dataList对象,驱动程序节点就无法从此远程对象中检索任何信息。

主程序和所谓的操作中的代码,即foreachcollecttake等,在主要执行线程或驱动程序节点。然后,当你运行

data.take(10).foreach(a => dataList += new Data(a._1.toDouble, a._2.toDouble))

take方法正在从工作人员那里获取RDD的前10个数据。所有代码都在驱动程序节点中执行,并且魔法工作。

如果您要构建RDD DataRDD对象,则必须将您直接阅读的信息转换为oringal val dataList: RDD[Data] = data.map(a => new Data(a._1.toDouble, a._2.toDouble)) 。尝试类似以下的内容:

{{1}}

还要看一下这篇文章:A new way to err, Apache Spark

希望它有所帮助。