Scala:如何将任何通用序列作为此方法的输入

Niy*_*yaz 0 scala dataframe apache-spark apache-spark-sql

Scala 菜鸟在这里。仍在努力学习语法。

我正在尝试减少将测试数据转换为 DataFrame 时必须编写的代码。这是我现在所拥有的:

  def makeDf[T](seq: Seq[(Int, Int)], colNames: String*): Dataset[Row] = {
    val context = session.sqlContext
    import context.implicits._
    seq.toDF(colNames: _*)
  }
Run Code Online (Sandbox Code Playgroud)

问题是上述方法只需要一个形状序列Seq[(Int, Int)]作为输入。如何让它以任何序列作为输入?我可以将输入形状更改为Seq[AnyRef],但是代码无法将toDF调用识别为有效符号。

我无法弄清楚如何进行这项工作。有任何想法吗?谢谢!

Ass*_*son 5

简短的回答:

import scala.reflect.runtime.universe.TypeTag

def makeDf[T <: Product: TypeTag](seq: Seq[T], colNames: String*): DataFrame = ...
Run Code Online (Sandbox Code Playgroud)

解释:

当您调用 seq.toDF 时,您实际上是在使用 SQLImplicits 中定义的隐式:

implicit def localSeqToDatasetHolder[T : Encoder](s: Seq[T]): DatasetHolder[T] = {
  DatasetHolder(_sqlContext.createDataset(s))
}
Run Code Online (Sandbox Code Playgroud)

这反过来又需要生成一个编码器。问题是编码器仅在某些类型上定义。特别是 Product(即元组、case 类等)您还需要添加隐式 TypeTag,以便 Scala 可以克服类型擦除(在运行时所有 Sequences 都具有类型序列,而不管泛型类型如何。TypeTag 提供了这方面的信息) .

作为侧节点,您不需要从会话中提取 sqlcontext,您可以简单地使用:

import sparkSession.implicits._
Run Code Online (Sandbox Code Playgroud)