2017-05-21 49 views
1

下面是我的代碼:斯卡拉:無法從RDD賦值ArrayBuffer

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記錄。

現在,當我嘗試使用帶

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() 
0

該問題與您的代碼執行的位置有關。一個變換內作出的每項操作,即一個mapflatMapreduce,等等,在主線程(或在駕駛員節點)不執行,但在工人節點。這些節點在不同於驅動程序節點的線程(或主機)中運行。

不存儲在RDD內部並且在工作節點中使用的每個對象都只存在於工作人員內存空間中。然後,您的dataList對象只是在每個工作人員中新創建,並且驅動程序節點無法從此遠程對象檢索任何信息。

在主程序,並在所謂的動作的代碼,即foreachcollecttake等,在主線程或驅動器節點被執行。然後,當你運行

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

take方法是從工人找回了RDD的第10個數據。所有代碼都在驅動程序節點中執行,並且具有魔法效果。

如果您想要構建Data對象的RDD,則必須將您直接讀取的信息轉換爲oringal RDD。嘗試類似如下的內容:

val dataList: RDD[Data] = 
    data.map(a => new Data(a._1.toDouble, a._2.toDouble)) 

嘗試看看也給這個帖子:A new way to err, Apache Spark

希望它有幫助。