Spark中如何在RDD的map操作中获取多列数据?
解决Spark RDD map操作中获取多列数据的问题
嘿,这个问题我太熟了!你遇到的其实是Scala表达式返回规则的小坑,我当初刚转Spark的时候也踩过~
为什么你的代码只返回最后一个值?
在Scala里,多个用分号分隔的表达式组成的代码块,最终只会返回最后一个表达式的结果。你写的x.get(0); x.getAs[String](1); x.get(3),前两个取值操作只是执行了,但没有把结果保留并返回,所以map算子最终只输出了x.get(3)的值,前面的相当于白忙活了。
正确的解决方式
要同时获取多列数据,你需要把这些值打包成一个可以容纳多个元素的结构,最常用的是元组(Tuple),如果追求可读性也可以用自定义的case class。
方式1:使用元组(最简洁直接)
直接把需要的列值放在括号里组成元组返回:
// 简洁写法 val dfrdd = df.map{x => (x.get(0), x.getAs[String](1), x.get(3))} // 或者拆成多行,可读性更好 val dfrdd = df.map{x => val col1Value = x.get(0) val col2Value = x.getAs[String](1) val col4Value = x.get(3) (col1Value, col2Value, col4Value) }
这样得到的RDD类型是RDD[(Any, String, Any)],如果知道列的具体类型,建议用getAs[具体类型]来指定,比如x.getAs[Int](0),这样类型会更明确,避免后续操作的类型转换问题。
方式2:使用Case Class(可读性更强)
如果后续需要频繁访问这些字段,推荐定义一个case class来封装数据,这样可以通过字段名直接访问,比元组的_1、_2更直观:
// 先定义对应结构的case class(注意要放在可访问的位置,比如object或者class外面) case class TargetRecord(col1: Int, col2: String, col4: Double) // 在map中构造case class实例返回 val dfrdd = df.map{x => TargetRecord( x.getAs[Int](0), x.getAs[String](1), x.getAs[Double](3) ) }
此时你的RDD类型是RDD[TargetRecord],后续操作时可以直接写record.col1、record.col2来获取对应的值,非常方便。
内容的提问来源于stack exchange,提问作者knowone
相关产品推荐
相关产品推荐

