我有一个名为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没有添加。 谢谢!
答案 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。 因此解决方案是使用火花累加器。