如何迭代记录火花scala?

时间:2015-10-09 05:45:38

标签: scala apache-spark avro

我有一个变量" myrdd"这是一个avro文件,通过hadoopfile加载了10条记录。

当我这样做时

myrdd.first_1.datum.getName()

我可以得到这个名字。问题是,我在" myrdd"中有10条记录。当我这样做时:

myrdd.map(x => {println(x._1.datum.getName())})

它不起作用并且一次打印出一个奇怪的对象。如何迭代所有记录?

1 个答案:

答案 0 :(得分:14)

以下是使用spark-shell并具有类似方案的会话的日志。

鉴于

scala> persons
res8: org.apache.spark.sql.DataFrame = [name: string, age: int]

scala> persons.first
res7: org.apache.spark.sql.Row = [Justin,19]

您的问题似乎是

scala> persons.map(t => println(t))
res4: org.apache.spark.rdd.RDD[Unit] = MapPartitionsRDD[10]

所以map只返回另一个RDD(该函数不会立即应用,该函数应用"懒惰"当您真正迭代结果时)。

因此,当您实现(使用collect())时,您会得到一个正常的"系列:

scala> persons.collect()
res11: Array[org.apache.spark.sql.Row] = Array([Justin,19])

你可以map。请注意,在这种情况下,您在传递给mapprintln)的闭包中有副作用,println的结果为Unit):

scala> persons.collect().map(t => println(t))
[Justin,19]
res5: Array[Unit] = Array(())

如果最后应用collect,结果相同:

scala> persons.map(t => println(t)).collect()
[Justin,19]
res19: Array[Unit] = Array(())

但是如果您只想打印行,可以将其简化为使用foreach

scala> persons.foreach(t => println(t))
[Justin,19]

正如@RohanAletty在评论中指出的那样,这适用于本地Spark作业。如果作业在群集中运行,则还需要collect

persons.collect().foreach(t => println(t))

注释

  • Iterator类中可以观察到相同的行为。
  • 上述会话的输出已重新排序

<强>更新

至于过滤:collect的位置是&#34;不好&#34;,如果您在collect之后应用可以在之前应用的过滤器。

例如,这些表达式给出了相同的结果:

scala> persons.filter("age > 20").collect().foreach(println)
[Michael,29]
[Andy,30]

scala> persons.collect().filter(r => r.getInt(1) >= 20).foreach(println)
[Michael,29]
[Andy,30]

但第二种情况更糟,因为该过滤器可能已在collect之前应用。

同样适用于任何类型的聚合。