将Spark Dataframe转换为可变Map

时间:2017-10-19 20:23:17

标签: scala dictionary apache-spark dataframe collections

我是新来的火花和斯卡拉。我正在尝试查询配置单元中的表(从表中选择2列)并将结果数据帧转换为映射。我使用Spark 1.6和Scala 2.10.6。

例如:

Dataframe:
+--------+-------+
| address| exists|
+--------+-------+
|address1|   1   |
|address2|   0   |
|address3|   1   |
+--------+-------+ 
should be converted to: Map("address1" -> 1, "address2" -> 0, "address3" -> 1)

这是我正在使用的代码:

val testMap: scala.collection.mutable.Map[String,Any] = Map()
val df= hiveContext.sql("select address,exists from testTable")
qualys.foreach( r => {
  val key = r(0).toString
  val value = r(1)
  testMap+=(key -> value)
  }
)
testMap.foreach(println)

当我运行上面的代码时,我收到此错误:

java.lang.NoSuchMethodError: scala.Predef$.ArrowAssoc(Ljava/lang/Object;)Ljava/lang/Object;

在我尝试将键值对添加到Map的行中抛出此错误。即testMap+=(key -> value)

我知道使用org.apache.spark.sql.functions.map有更好更简单的方法。但是,我使用Spark 1.6,我不认为这个功能可用。我尝试了import,但我没有在可用功能列表中找到它。

为什么我的方法会给我一个错误?是否有一种更好/更优雅的方式来实现火花1.6?

任何帮助将不胜感激。谢谢!

更新

我将元素添加到Map的方式更改为以下内容:testMap.put(key, value)

我以前使用+=添加元素。现在我不再获得java.lang.NoSuchMethodError了。但是,testMap没有添加任何元素。在foreach步骤完成后,我尝试打印地图的大小及其中的所有元素,我发现有zero个元素。

为什么元素没有被添加?我也对任何其他更好的方法持开放态度。谢谢!!

2 个答案:

答案 0 :(得分:2)

这可分为3个步骤,每个步骤已在SO上解决:

  1. 将DataFrame转换为RDD[(String, Int)]
  2. 在该RDD上调用collectAsMap()以获取不可变的地图
  3. 将该地图转换为可变地图(例如,如here所述)
  4. 注意:我不知道你为什么需要可变地图 - 值得注意的是,使用 mutable 集合很少有意义在斯卡拉。坚持使用不可变对象只是更安全,更容易推理。 “忘记”可变集合的存在使学习功能API(如Spark的!)变得更加容易。

答案 1 :(得分:2)

只需从数据框中收集数据并在其上进行迭代,它就可以正常工作

qualys.collect.map( r => {
val key = r(0).toString
val value = r(1)
testMap+=(key -> value)
 }
)