2016-03-24 97 views
1

我想在循環中向一個Scala ListBuffer添加一些對象,但是每次添加一個對象時,它都會在循環的下一次迭代中消失。Scala - ListBuffer在每次添加循環後清空本身

當我之前並添加新條目後打印ListBuffer的內容,我得到下面的輸出:

加前:ListBuffer()

後添加:ListBuffer(com.me .FeatureV2 @ 20d953ba)

加前:ListBuffer()

後添加:ListBuffer([email protected]

加前:ListBuffer()

後添加:ListBuffer([email protected]

代碼:

def generateStatistics(df: DataFrame): List[FeatureV2] = { 
    var features = ListBuffer[FeatureV2]() 
    val dataColumn = "data" 
    for (field <- df.schema.fieldNames){ 
     val columnType: String = df.select(field).dtypes(0)._2 

     if (columnType == StringType.toString){ 
     val statsDf: DataFrame = getStats(df, field, dataColumn) 
     for (row <- statsDf){ 
      println("Before add: " + features) 
      val feature = new FeatureV2() 
      feature.element = row.getString(0) 
      feature.count = row.getLong(1) 
      feature.sum = row.getDouble(2) 
      feature.max = row.getDouble(3) 
      feature.min = row.getDouble(4) 
      feature.feature = field 
      features += feature 
      println("After add: " + features) 
     } 
     } 
    } 
    features.toList 
    } 

有時不過,我得到以下幾點:

加入前:ListBuffer()

後添加:ListBuffer([email protected]

加前:ListBuffer([email protected]

後添加:ListBuffer([email protected], COM .me.FeatureV2 @ 4b0df9e5)

加前:ListBuffer()

後添加:ListBuffer([email protected]

這看起來像它實際上是普惠在ListBuffer中,但它已被清除。與垃圾收集有關嗎?

+0

你確定你只調用一次'generateStatistics''嗎? –

+0

@JeanLogeart是的,絕對。 – karoma

+1

在附註中,請使用ListBuffer作爲val並使用+ =([see here](http://docs.scala-lang.org/overviews/collections/concrete-mutable-collection-classes.html ))。這很奇怪,很難推理,因爲你正在修改對象引用。 – slouc

回答

3

嘗試將for (row <- statsDf)更改爲for (row <- statsDf.collect())

如果這可以解決您的問題,那麼您的問題可能是由於foreach正在一個或多個線程中運行引起的。

for (row <- stadsDf)是實際調用DataFrame.foreach(f: Row => Unit),這是一個分佈式foreach其中f可以在任意數量取決於你的星火主線程或機器的運行。

2

Spark應用程序由驅動程序和執行程序組成。您可以通過Driver來控制和創建事物 - 執行者獲取範圍內的變量副本。所以,執行者獲得ListBuffer的副本。他們附加到他們的副本,任務完成時會丟失副本。

你可以使用collect()的數據拉入驅動程序追加到ListBuffer那裏,或者使用廣播的變量。

請參閱the documentation討論。

0

是可變的集合嗎?

另外,當使用Scala時,應該盡力做FP。

df.schema.fieldNames.map {...} 

可能會做你需要的工作。因爲你有一個if也許collect將被更多佔用