scala var无法在foreach循环外获取附加值

时间:2015-10-14 03:57:57

标签: scala foreach apache-spark

我有一个名为vertexDict的文本文件,它有多个由“\ 1”分割的键值对,我需要将它转换为我的spark程序中的Map。这是我的代码:

var mapDict = Map[Long, String]()
sc.textFile(vertexDict).map(line=> line.split("\1")).foreach(a=>{
  if(a.length ==2 ){
    mapDict += a(0).toLong->a(1)
  }
})

问题是在foreach循环结束后mapDict仍然是空的,但我进入了循环,mapDict成功地将元素添加到其中;所以我绕过了这个问题:

val mapDict = sc.textFile(vertexDict).map(line=> line.split("\1")).map(a=>a(0).toLong->a(1)).collect().toMap

它有效。但我仍然不知道为什么foreach没有添加。 谢谢!

3 个答案:

答案 0 :(得分:0)

您的逻辑似乎存在一些问题。正确的逻辑是:

var mapDict = Map[Long, String]()
val str = "1234\1hello\n3456\1world"
str.lines.foreach{line => 
  val a = line.split("\1")
  if(a.length == 2) {
    mapDict += (a(0).toLong->a(1))
  }
}

这是输出:

scala> mapDict foreach println
(1234,hello)
(3456,world)

答案 1 :(得分:0)

这是解决问题的必要方法。 FP方法是将其视为一组线条,您可以从中生成从符合特定条件的线条(此处有两个项目)中获取的地图。尝试:

val str = "1234\1hello\nNonmatching line\n3456\1world\nAline\1with too\1many matches"
val mapDict = str.lines.map( a => a.split("\1")).collect {case Array(k,v) => k->v}.toMap

我添加了1个项目行和3个项目行,以证明它们已被过滤掉。这给出了:

mapDict: scala.collection.immutable.Map[String,String] = Map(1234 -> hello, 3456 -> world)

请注意,您不需要将mapDict变为var。

答案 2 :(得分:0)

我终于知道为什么在foreach循环中修改Map集合并不起作用:因为spark并行运行并且地图集合在不同的分区中被更改,我在我的问题中粘贴的解决方案只是使用rdd操作collect来将所有分区数据获取到驱动程序并在本地运行toMap。 因此解决方案是使用火花累加器。