为什么在foreach中打印并不能反映元素的顺序

时间:2016-01-03 03:03:55

标签: scala apache-spark

可能是我遗漏了一些东西,但我希望根据密钥

对数据进行排序
scala> val x=sc.parallelize(Array( "cat", "ant", "1"))
x: org.apache.spark.rdd.RDD[String] = ParallelCollectionRDD[160] at parallelize at <console>:22

scala> val xxx=x.map(v=> (v,v.length))
xxx: org.apache.spark.rdd.RDD[(String, Int)] = MapPartitionsRDD[161] at map at <console>:26

scala> xxx.sortByKey().foreach(println)
(1,1)
(cat,3)
(ant,3)

scala> xxx.sortByKey().foreach(println)
(cat,3)
(1,1)
(ant,3)

如果我告诉spark只使用下面的1个分区,但是如何在群集或超过1个工作人员中使用它?

scala> xxx.sortByKey(numPartitions=1).foreach(println)
(1,1)
(ant,3)
(cat,3)

更新:

我想我得到了答案。当我使用collect

时,它正在正确排序
scala> xxx.sortByKey().collect
res170: Array[(String, Int)] = Array((1,1), (ant,3), (cat,3))

保持问题的开放,以验证我的理解。

2 个答案:

答案 0 :(得分:2)

这是有道理的。 foreach跨分区并行运行,这会产生非确定性排序。订单可能是混合的。 collect为您提供按排序顺序连接的分区数组。

答案 1 :(得分:1)

请查看spark documentation为什么collect()方法为您解决了问题。

e.g。

val lines = sc.textFile("data.txt")
val pairs = lines.map(s => (s, 1))
val counts = pairs.reduceByKey((a, b) => a + b)
  

例如,我们也可以使用counts.sortByKey()来按字母顺序对这些对进行排序,最后使用counts.collect()将它们作为对象数组返回给驱动程序。

在生成的RDD上调用collect()将返回或输出有序的记录列表

collect()
  

在驱动程序中将数据集的所有元素作为数组返回。在过滤器或其他返回足够小的数据子集的操作之后,这通常很有用。

请记住对非常大的分布式RDD collect()执行can cause your driver program to run out of memory and crash操作操作。因此,除了在小型数据集上对Spark程序进行原型设计时,不要使用collect()。

有关详细信息,请查看此article

<强> 编辑:

sortByKey():按键对RDD进行排序,以便每个分区都包含已排序的元素范围。由于所有分区可能不在同一个Executor节点中,因此除非您致电collect()

,否则不会获得有序集