Scala Spark如何将Array[(String,String,String)]转为嵌套Map
Scala 中三元组数组转嵌套Map实现
基础场景(无重复一级key)
如果输入数组里三元组第一个元素(一级key)不会重复,直接映射转换即可:
val inputArray: Array[(String,String,String)] = Array(("elem1","elem2","elem3"),("elem4","elem5","elem6")) val outputMap: Map[String, Map[String, String]] = inputArray .map { case (topKey, subKey, subValue) => topKey -> Map(subKey -> subValue) } .toMap
运行后输出和预期结果完全一致:
scala> println(outputMap) Map(elem1 -> Map(elem2 -> elem3), elem4 -> Map(elem5 -> elem6))
兼容一级key重复场景
如果存在多个三元组第一个元素相同的情况,上面的写法会因为toMap的默认逻辑,用后面出现的条目覆盖前面的同key条目。如果需要把同一个一级key下的所有二级键值对合并到同一个子Map里,用groupBy实现:
val outputMapMerge: Map[String, Map[String, String]] = inputArray .groupBy(_._1) .map { case (topKey, tupleList) => // 提取同个一级key下的所有二级键值对转成子Map topKey -> tupleList.map(t => (t._2, t._3)).toMap }
Spark 开发场景适配
如果是在Spark作业中处理分布式数据集,不需要把数据收集到Driver端的话,可以直接在RDD层面做转换:
import org.apache.spark.rdd.RDD // 示例中从输入数组生成RDD,实际开发中为从数据源读取生成的RDD val sourceRdd: RDD[(String, String, String)] = spark.sparkContext.parallelize(inputArray) val nestedPairRdd: RDD[(String, Map[String, String])] = sourceRdd .map { case (topKey, subKey, subValue) => (topKey, (subKey, subValue)) } .groupByKey() .mapValues(iter => iter.toMap) // 如果需要最终在Driver端拿到本地嵌套Map,调用收集方法即可 val localOutputMap: Map[String, Map[String, String]] = nestedPairRdd.collectAsMap()
注意:如果数据量很大,不要随意调用
collectAsMap把全量数据拉到Driver端,避免Driver内存溢出。
内容的提问来源于stack exchange,提问作者Azo
相关产品推荐
相关产品推荐

