我想创建一个应该用案例类T实现的Scala特征 . 特性只是加载数据并将其转换为类型为T的Spark数据集 . 我得到的错误是没有编码器可以存储,我认为是因为Scala不知道T应该是一个案例类 . 我该如何告诉编译器?我已经看到某个地方我应该提到Product,但是没有定义这样的类...请随意提出其他方法来做到这一点!
我有以下代码,但它没有编译错误:42:错误:无法找到存储在数据集中的类型的编码器 . 导入sqlContext.implicits._ [INFO] .as [T]支持原始类型(Int,String等)和产品类型(case类)
我正在使用Spark 1.6.1
码:
import org.apache.spark.{SparkConf, SparkContext}
import org.apache.spark.sql.{Dataset, SQLContext}
/**
* A trait that moves data on Hadoop with Spark based on the location and the granularity of the data.
*/
trait Agent[T] {
/**
* Load a Dataframe from the location and convert into a Dataset
* @return Dataset[T]
*/
protected def load(): Dataset[T] = {
// Read in the data
SparkContextKeeper.sqlContext.read
.format("com.databricks.spark.csv")
.load("/myfolder/" + location + "/2016/10/01/")
.as[T]
}
}
2 回答
您的代码缺少3件事:
确实,你必须让编译器知道T是
Product
的子类(所有Scala案例类和元组的超类)编译器还需要实际案例类的
TypeTag
和ClassTag
. Spark隐式使用它来克服类型擦除导入
sqlContext.implicits._
不幸的是,您无法在特征中添加带有上下文边界的类型参数,因此最简单的解决方法是使用
abstract class
代替:显然,这不是最适合这份工作的 . 另一种方法是将
load
放在一个对象中并将type参数移动到该方法:哪一个更可取的主要取决于您将在何处以及如何调用
load
以及您计划对结果做什么 .你需要采取两个行动:
在您的导入中添加
import sparkSession.implicits._
让你的特质
trait Agent[T <: Product]