2017-11-28 7 views
1

これは私にとってかなり奇妙です。私はScalaのmapforeachの違いと両方の使用例に精通していますが、私は他の何かを理解していないかもしれません。私はスパークで遊んでいたときに初めてこれに遭遇しました。これはおそらく、これがRDDを使用しているときにしか現れません。Scalaは外見上いくつかのコードを無視しています

マップへの呼び出しが一見無視される以下のコードがあります。 私はScala 2.11.1を使用しています。以下のコードを実行するための私の依存関係です。あなたは何をstdoutに印刷されていないことを確認することができ、これを実行している場合は

libraryDependencies ++= Seq(
    "org.apache.spark" %% "spark-core" % "2.1.0", 
    "org.apache.spark" %% "spark-sql" % "2.1.0" 
) 

以下は、Scalaのコンソールに

import org.apache.spark.SparkConf 
import org.apache.spark.SparkContext 
import org.apache.spark.SparkContext._ 
import org.apache.spark.rdd.RDD 
import org.apache.spark.RangePartitioner 

val conf: SparkConf = new SparkConf().setMaster("local").setAppName("Test") 
val sc: SparkContext = new SparkContext(conf) 


val rdd: RDD[Tuple2[String, String]] = sc.parallelize(List(
    ("I", "India"), 
    ("U", "USA"), 
    ("W", "West"))) 

val rp = new RangePartitioner(3, rdd) 
val parts = rdd.partitionBy(rp).cache() 

parts.mapPartitionsWithIndex((x,y) => { y.map(println); y }).collect() 

を貼り付けることができます。ただし、コードの最後の行をparts.mapPartitionsWithIndex((x,y) => { y.map(println) }).collect()に変更した場合、またはそれでもparts.mapPartitionsWithIndex((x,y) => { y.foreach(println); y }).collect()に変更した場合は、それが印刷されます。

これは、私がローカルモードになってから出力されないstdoutについての質問とは異なると思います。これはRDDの評価に問題ではなく、stdoutです。

mapPartitionsWithIndexに渡された関数の種類はあなたの例ではそう (Int, Iterator[T]) ⇒ Iterator[U]ある
+0

正確には印刷されません。 –

+0

インポートの完全なコード例では、何もstdoutに出力されません。おそらく、セットアップの問題ですが、すべての例でstdoutで何かを見ることができるのであれば。 – mschuett

+0

これはローカルで実行していますか?そしてplzは正確なコード差で実行されない場合を指定します –

答えて

3

は、yがあるIterator

結果が必要になるまでのScala Iterator

は怠惰なコレクションは、言い換えれば、それはどんな仕事をしないで(RDDと同様)。コード(x,y) => { y.map(println); y }マップ変換で

は、各要素が、評価されたとき、プリントアウト及びUnitで置換される新しいIteratorを返します。次に、このイテレータを破棄して元の値に戻し、出力と同じ入力をRDDとします。 mapによって生成されるイテレータは決して使用されないので、関数は評価されず、何も出力されません。

"working"コードでは、(x,y) => { y.map(println)}は同じマッピング変換を適用しますが、生成するイテレータは戻ります。したがって、RDDを変換(collectを使用)から作成すると、行が印刷されます(結果としてRDDにはすべてUnitの値が含まれます)。

(x,y) => { y.foreach(println); y }代わりに、イテレータの各要素を厳密に評価してUnitを返すforeachを使用します。次に、入力イテレータを返します(すでにすべての要素を消費しているので、空です)。 RDDcollectと評価されると、このブロックが実行され、要素が出力されます。その結果のRDDが空であることに注意してください。

+0

申し訳ありませんが、簡単に言うと、最初のケースには 'action'が含まれていないため、2番目のケースには???があります – nabongs

+0

@cueアクションはスパーク特有の用語です。ここでは、Iteratorについて説明しています。それは基本的に同じ考えです。イテレータ上の 'map'はすぐには何もしませんが、新しいイテレータを返します。評価されると、各要素はマップに渡された関数に渡されます。返されるイテレータで何もしないと、 'map'のコードは決して実行されません。 – puhlen

+0

これを説明してくれてありがとう!私はスパークの怠惰な評価をある程度理解していましたが、理にかなった子供のRDDにも適用されていることを理解していませんでした。ほとんどの場合、パーティションがRDDを返すとは考えていませんでした...もちろん、あなたの答えを読んだ後もどちらも理にかなっています。 – mschuett

関連する問題