scala Hashset包含重复项

时间:2018-04-22 11:19:19

标签: scala apache-spark duplicates hashset

我有一个可变的哈希集,我在其中添加文本文件中的元素,但也添加了重复项。 我的代码是

val machines = new mutable.HashSet[String]

val splitRdd = textFile.flatMap(line => {
val l =line.split("\\t").toList
machines.add(l(2))
machines})

splitRdd.foreach(rdd=> println(rdd))
splitRdd.saveAsTextFile(outputFile)

文本文件是:

0   0   m2  0   0   0  
0   0   m2  0   0   0  
0   0   m3  0   0   0  
0   0   m3  0   0   0  

我在输出文件和spark中的stdout中得到的是:

m2  
m2  
m2  
m3  
m3

除了添加重复项之外,还有一个' m2'在文件中不存在。我认为我的代码是正确的,有谁知道为什么会这样?

1 个答案:

答案 0 :(得分:2)

好吧,看起来你跳过Spark Programming Guide(简短,但强烈推荐的讲座)。特别是名为Understanding closures的部分:

  

Spark的一个难点是在跨集群执行代码时理解变量和方法的范围和生命周期。修改其范围之外的变量的RDD操作可能经常引起混淆。

长话短说,Spark中没有共享内存(不要将共享内存与所谓的shared variable混淆,这些内存并非真正共享)。您的代码的作用如下:

  • 它检测到闭包内部使用了machines
  • 序列化值,发送到每个执行程序节点,然后反序列化以创建本地副本
  • 然后您的代码修改此本地副本,每个执行程序线程独立于其他副本工作。没有涉及同步,因此您所做的就是对各个分区进行重复数据删除。

您的代码可能local模式工作(取决于声明machines的确切上下文),但通常您应该看到驱动程序副本是永远不会修改,并且在执行代码后它是空的。

你应该在这里做的是:

textFile.flatMap(_.split("\\t")).distinct.saveAsTextFile(outputFile)

这样,Spark会对各个分区进行重复数据删除,对数据进行重排,以确保剩余的重复项驻留在相同的分区上,然后重复分区。

此处带走的消息只是阅读手册。它将来会省去很多麻烦。