我有一个scala-2.11函数,它根据提供的类类型从Map创建一个case类。
def createCaseClass[T: TypeTag, A](someMap: Map[String, A]): T = {
val rMirror = runtimeMirror(getClass.getClassLoader)
val myClass = typeOf[T].typeSymbol.asClass
val cMirror = rMirror.reflectClass(myClass)
// The primary constructor is the first one
val ctor = typeOf[T].decl(termNames.CONSTRUCTOR).asTerm.alternatives.head.asMethod
val argList = ctor.paramLists.flatten.map(param => someMap(param.name.toString))
cMirror.reflectConstructor(ctor)(argList: _*).asInstanceOf[T]
}
我试图在火花数据帧的上下文中将其用作UDF。但是,我不确定通过案例类的最佳方法是什么。以下方法似乎不起作用。
def myUDF[T: TypeTag] = udf { (inMap: Map[String, Long]) =>
createCaseClass[T](inMap)
}
我正在寻找类似的东西 -
case class MyType(c1: String, c2: Long)
val myUDF = udf{(MyType, inMap) => createCaseClass[MyType](inMap)}
感谢您解决此问题的想法和建议。
答案 0 :(得分:2)
但是,我不确定通过案例类
的最佳方法是什么
不可能将case类用作用户定义函数的参数。 SQL StructTypes
被映射为动态类型(缺少更好的单词)Row
个对象。
如果您想对静态类型的对象进行操作,请使用静态类型Dataset
。
答案 1 :(得分:1)
从try和error中我了解到,存储在Dataframe或Dataset中的数据结构都是使用org.apache.spark.sql.types
您可以看到:
df.schema.toString
像Int,Double这样的基本类型存储如下:
StructField(fieldname,IntegerType,true),StructField(fieldname,DoubleType,true)
像case类这样的复杂类型被转换为嵌套类型的组合:
StructType(StructField(..),StructField(..),StructType(..))
示例代码:
case class range(min:Double,max:Double)
org.apache.spark.sql.Encoders.product[range].schema
//Output:
org.apache.spark.sql.types.StructType = StructType(StructField(min,DoubleType,false), StructField(max,DoubleType,false))
在这种情况下,UDF参数类型是Row,或者在存储案例类数组时的Seq [Row]
基本的调试技术是打印到字符串:
val myUdf = udf( (r:Row) => r.schema.toString )
然后,看到发生了:
df.take(1).foreach(println) //