web-dev-qa-db-ja.com

Spark RDDforeach内のコレクションを変更する

RDDの要素を繰り返しながら、マップに要素を追加しようとしています。エラーは発生していませんが、変更は行われていません。

直接追加したり、他のコレクションを繰り返したりすると、すべて正常に機能します。

scala> val myMap = new collection.mutable.HashMap[String,String]
myMap: scala.collection.mutable.HashMap[String,String] = Map()

scala> myMap("test1")="test1"

scala> myMap
res44: scala.collection.mutable.HashMap[String,String] = Map(test1 -> test1)

scala> List("test2", "test3").foreach(w => myMap(w) = w)

scala> myMap
res46: scala.collection.mutable.HashMap[String,String] = Map(test2 -> test2, test1 -> test1, test3 -> test3)

しかし、RDDから同じことをしようとすると:

scala> val fromFile = sc.textFile("tests.txt")
...
scala> fromFile.take(3)
...
res48: Array[String] = Array(test4, test5, test6)

scala> fromFile.foreach(w => myMap(w) = w)
scala> myMap
res50: scala.collection.mutable.HashMap[String,String] = Map(test2 -> test2, test1 -> test1, test3 -> test3)

変数が同じであることを確認するために、foreachの前と同じようにマップの内容を印刷しようとしましたが、正しく印刷されます。

fromFile.foreach(w => println(myMap("test1")))
...
test1
test1
test1
...

また、foreachコード内にマップの変更された要素を印刷し、変更されたものとして印刷しましたが、操作が完了すると、マップは変更されていないように見えます。

scala> fromFile.foreach({w => myMap(w) = w; println(myMap(w))})
...
test4
test5
test6
...
scala> myMap
res55: scala.collection.mutable.HashMap[String,String] = Map(test2 -> test2, test1 -> test1, test3 -> test3)

RDDを配列(収集)に変換することも正常に機能します。

fromFile.collect.foreach(w => myMap(w) = w)
scala> myMap
res89: scala.collection.mutable.HashMap[String,String] = Map(test2 -> test2, test5 -> test5, test1 -> test1, test4 -> test4, test6 -> test6, test3 -> test3)

これはコンテキストの問題ですか?他の場所で変更されているデータのコピーにアクセスしていますか?

15
palako

Sparkクラスター(単一のマシンではない)で実行すると、より明確になります。RDDは複数のマシンに分散されるようになりました。foreachを呼び出すと、各マシンに何をするかを指示します。持っているRDDの一部を処理します。ローカル変数(myMapなど)を参照すると、それらはシリアル化されてマシンに送信されるため、使用できます。しかし、何も返されません。 myMapの元のコピーは影響を受けません。

これはあなたの質問に答えると思いますが、明らかにあなたは何かを成し遂げようとしていて、この方法でそこにたどり着くことはできません。ここで、または別の質問で、あなたが何をしようとしているのかを自由に説明してください。私がお手伝いします。

33
Daniel Darabos