Scala 基于不同案例类创建数据集
嗨,我有一个RDD,它基本上是在读取CSV文件后生成的。 我定义了一个方法,它基本上根据输入参数将rdd的行映射到不同的案例类 返回的RDD需要转换为数据帧 当我尝试运行相同的程序时,我得到以下错误 定义的方法是Scala 基于不同案例类创建数据集,scala,apache-spark,pattern-matching,case-class,Scala,Apache Spark,Pattern Matching,Case Class,嗨,我有一个RDD,它基本上是在读取CSV文件后生成的。 我定义了一个方法,它基本上根据输入参数将rdd的行映射到不同的案例类 返回的RDD需要转换为数据帧 当我尝试运行相同的程序时,我得到以下错误 定义的方法是 case class Australiafile1(sectionName: String, profitCentre: String, valueAgainst: String, Status: String) case class Australiafile2(secti
case class Australiafile1(sectionName: String, profitCentre: String, valueAgainst: String, Status: String)
case class Australiafile2(sectionName: String, profitCentre: String)
case class defaultclass(error: String)
def mapper(line: String, recordLayoutClassToBeUsed: String) = {
val fields = line.split(",")
var outclass = recordLayoutClassToBeUsed match {
case ("Australiafile1") => Australiafile1(fields(0), fields(1), fields(2), fields(3))
case ("Australiafile2") => Australiafile2(fields(0), fields(1))
}
outclass
}
方法的输出用于创建数据帧,如下所示
val inputlines = spark.sparkContext.textFile(inputFile).cache().mapPartitionsWithIndex { (idx, lines) => if (idx == 0) lines.drop(numberOfLinesToBeRemoved.toInt) else lines }.cache()
val records = inputlines.filter(x => !x.isEmpty).filter(x => x.split(",").length > 0).map(lines => mapper(lines, recordLayoutClassToBeUsed))
import spark.implicits._
val recordsDS = records.toDF()
recordsDS.createTempView("recordtable")
val output = spark.sql("select * from recordtable").toDF()
output.write.option("delimiter", "|").option("header", "false").mode("overwrite").csv(outputFile)
收到的错误如下所示
线程“main”java.lang.NoClassDefFoundError中出现异常:未找到与可序列化的产品对应的java类
位于scala.reflect.runtime.JavaMirrors$JavaMirror.typeToJavaClass(JavaMirrors.scala:1300)
位于scala.reflect.runtime.JavaMirrors$JavaMirror.runtimeClass(JavaMirrors.scala:192)
位于scala.reflect.runtime.JavaMirrors$JavaMirror.runtimeClass(JavaMirrors.scala:54)
位于org.apache.spark.sql.catalyst.encoders.ExpressionEncoder$.apply(ExpressionEncoder.scala:60)
位于org.apache.spark.sql.Encoders$.product(Encoders.scala:275)
在org.apache.spark.sql.LowPrioritySQLImplicits$class.newProductEncoder上(SQLImplicits.scala:233)
位于org.apache.spark.sql.SQLImplicits.newProductEncoder(SQLImplicits.scala:33)
您能告诉我这有什么问题吗?我如何克服这一问题?试试:
trait AustraliaFile extends Serializable
case class Australiafile1(sectionName: String, profitCentre: String, valueAgainst: String, Status: String) extends AustraliaFile
case class Australiafile2(sectionName: String, profitCentre: String) extends AustraliaFile
您的类不是可序列化的,但是Spark只能编写可序列化的对象。另外,将相关类基于一个共同的祖先总是一个好主意,这样您就可以将RDD声明为RDD[AustraliaFile]
而不是RDD[Any]
此外,您的类匹配逻辑可以简化为
def mapper(line: String, recordLayoutClassToBeUsed: String) = {
val fields = line.split(",")
recordLayoutClassToBeUsed match {
case ("Australiafile1") => Australiafile1(fields(0), fields(1), fields(2), fields(3))
case ("Australiafile2") => Australiafile2(fields(0), fields(1))
}
}
case类应该在主类之外编写——它们只在主方法之外。此外,如果我只从映射器方法返回一个case类对象,而不匹配和检查条件,则不会出现错误