2016-03-24 9 views
1

Scala ListBufferにループ内のいくつかのオブジェクトを追加しようとしていますが、追加するたびにループの次の繰り返しで消えます。追加した後ListBuffer()Scala - ループ内のすべてのループの後に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]、 コム.me.FeatureV2 @ 4b0df9e5)

追加する前に:ListBuffer()追加した後

:それは実際にpopulaがあるようListBuffer([email protected]

これが見えますListBufferを呼び出していますが、クリアされています。ガベージコレクションとは何か?

+0

'' generateStatistics''を1回だけ呼び出すのですか? –

+0

@JeanLogeartはい、間違いなく。 – karoma

+1

補足として、ListBufferをvalとして使用し、+ =([ここをクリック](http://docs.scala-lang.org/overviews/collections/concrete-mutable-collection-classes.html)を使用して追加してください。 ))。これはオブジェクト参照を変更しているので、理性的ではありません。 – slouc

答えて

3

for (row <- statsDf)for (row <- statsDf.collect())に変更してみてください。

これで問題が解決した場合は、foreachが1つ以上のスレッドで実行されていることが原因の可能性があります。

for (row <- stadsDf)fがあなたのスパークマスターに応じて、スレッドや、任意の数のマシン上で実行される分散foreachで実際に呼び出すDataFrame.foreach(f: Row => Unit)、です。

2

Sparkアプリケーションは、ドライバとエグゼキュータで構成されています。ドライバからの制御と作成 - エグゼキュータは範囲内の変数のコピーを取得します。したがって、エグゼクティブはListBufferのコピーを入手します。それらはコピーに追加され、タスクが完了すると失われます。

collect()を使用して、ドライバにデータをプルしてListBufferに追加するか、ブロードキャスト変数を使用できます。

the documentationを参照してください。

0

は変更可能ですか?

また、Scalaを使用する場合は、FPを行う際に努力する必要があります。

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

あなたが必要とする作業を行うでしょう。 ifを持っているので、collectがより適切になるでしょう。