以下是我的代码:
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中。
请帮忙。
答案 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)
问题与您的代码执行位置有关。在转换中进行的每个操作,即map
,flatMap
,reduce
等,都不会在主线程中执行(或在< em> driver node),但在 worker 节点中。这些节点在不同于驱动程序节点的线程(或主机)中运行。
未存储在RDD
内并且在工作节点中使用的每个对象仅存在于工作器内存空间中。然后,只需在每个worker中新创建dataList
对象,驱动程序节点就无法从此远程对象中检索任何信息。
主程序和所谓的操作中的代码,即foreach
,collect
,take
等,在主要执行线程或驱动程序节点。然后,当你运行
data.take(10).foreach(a => dataList += new Data(a._1.toDouble, a._2.toDouble))
take
方法正在从工作人员那里获取RDD
的前10个数据。所有代码都在驱动程序节点中执行,并且魔法工作。
如果您要构建RDD
Data
个RDD
对象,则必须将您直接阅读的信息转换为oringal val dataList: RDD[Data] =
data.map(a => new Data(a._1.toDouble, a._2.toDouble))
。尝试类似以下的内容:
{{1}}
还要看一下这篇文章:A new way to err, Apache Spark。
希望它有所帮助。