我使用Spark 2.1.1。
我从以下开始:
import org.apache.spark.sql.types._
val mySchema = StructType(
StructField("id", IntegerType, true),
StructField("code", StringType, false),
StructField("value", DecimalType, false))
val myDS = Seq((1,"000010", 1.0), (2, "000020", 2.0)).as[mySchema]
在这里,我看到mySchema不是一个类型,在查看Encoders.scala
后,我可以看到我需要通过
def product[T <: Product : TypeTag]: Encoder[T] = ExpressionEncoder()
因此,在看到冒号运算符只是来自What are Scala context and view bounds?的隐式参数的语法糖之后,我可以看到应该有一个隐含的 TypeTag [T] 可用,但我不知道但是要了解 TypeTag [T] 在查看SQLImplicits.scala
时是如何隐含的。
/**
* @since 1.6.1
* @deprecated use [[newSequenceEncoder]]
*/
def newProductSeqEncoder[A <: Product : TypeTag]: Encoder[Seq[A]] = ExpressionEncoder()
即使它被弃用了,当我看到
时 /** @since 2.2.0 */
implicit def newSequenceEncoder[T <: Seq[_] : TypeTag]: Encoder[T] = ExpressionEncoder()
我仍然想知道隐含声明的 TypeTag [T] 在哪里?
答案 0 :(得分:5)
TypeTag
是一个类型类,它将为您尝试召唤的任何类型隐式加载实例。这与Spark或SQLImplicits
无关,例如你可以试试这个
def getMyTypeTag[T : TypeTag]: TypeTag[T] = implicitly[TypeTag[T]]
另一方面,只要导入Encoder
中定义的含义,就可以通过spark构建spark sql SqlImplicits
,如果你看一下LowPrioritySQLImplicits
就可以看到您需要TypeTag
为Encoder
创建Product
(案例类),这就是您需要在隐式上下文中加载TypeTag
的原因
trait LowPrioritySQLImplicits {
/** @since 1.6.0 */
implicit def newProductEncoder[T <: Product : TypeTag]: Encoder[T] = Encoders.product[T]
}
只有当您尝试召唤编码器的代码不是通用的或者TypeTag已经在上下文中时,才可以召唤TypeTag。例如
def loadEncoder(): Encoder[MyType] ={
import spark.implicits._
Encoder[MyType] // The type is here so it will work
}
另一方面
loadEncoder[MyType]
def loadEncoder[T](): Encoder[T] ={
import spark.implicits._
Encoder[T] // The type info is not here so it wont work
}
和
loadEncoder[MyType]
def loadEncoder[T: TypeTag](): Encoder[T] ={
import spark.implicits._
Encoder[T] // The type info is not here but the TypeTag is so it will work
}
答案 1 :(得分:1)
好的,我认为这是Spark的事情,但页面顶部有一个import语句
import scala.reflect.runtime.universe.TypeTag
当我查看API页面http://www.scala-lang.org/api/2.11.6/scala-reflect/index.html#scala.reflect.api.TypeTags时,我可以看到它正在处理。