当使用带有List的case类时,Dataframe.rdd.count抛出没有为实际参数找到适用的构造函数/方法

时间:2018-02-20 16:30:35

标签: scala apache-spark

我正在使用Spark 2.1.0并在2.1.1上检查了这个场景。 这对我来说非常奇怪,它似乎是一个序列化问题。 我正在使用包含scala List的case类,我遇到以下错误:

Executor task launch worker for task 1] [CodeGenerator.logError]: failed to compile: org.codehaus.commons.compiler.CompileException: File 'generated.java', Line 111, Column 64: No applicable constructor/method found for actual parameters "scala.collection.Seq"; candidates are: "com.minute.playground.WithList(scala.collection.immutable.List)"

/ * 001 * /

我创建了一个提示问题的简短示例代码

import org.apache.spark.sql.{Dataset, SparkSession}
case class Simple(str: String)
case class WithList(list : List[String])
object RddCountFailOnCaseClassWithList {

  def main(args: Array[String]): Unit = {
    val spark = SparkSession.builder.appName("WhyLikeThis").master("local[2]").enableHiveSupport.getOrCreate
    import spark.implicits._    
    val df1: Dataset[Simple] = spark.sqlContext.createDataFrame[Simple](List(new Simple("1"))).as[Simple]
    df1.show()
    println(df1.rdd.count())

    val df2: Dataset[WithList] = spark.sqlContext.createDataFrame[WithList](List(new WithList(List("1")))).as[WithList]
    df2.show()
    //This will fail !!! ? But why ?
    println(df2.rdd.count())
  }
}

我做错了什么? 我不应该在我的模型中使用List吗?

2 个答案:

答案 0 :(得分:3)

看起来像一个bug :) 你没有做错任何事。看起来List某处转换为Seq,代码生成器无法找到所需的构造函数。 你的代码可以使用spark 2.2.0,所以它已得到修复。

如果您想使用spark 2.1.0,可以尝试将实现更改为

import org.apache.spark.sql.{Dataset, SparkSession}

case class Simple(str: String)

case class WithSeq(list: Seq[String])

object RddCountFailOnCaseClassWithList {

  def main(args: Array[String]): Unit = {
    val spark = SparkSession.builder.appName("WhyLikeThis").master("local[2]").enableHiveSupport.getOrCreate
    import spark.implicits._
    val df1: Dataset[Simple] = {
      spark.sqlContext.createDataFrame[Simple](List(Simple("1"))).as[Simple]
    }
    df1.show()
    println(df1.rdd.count())

    val df2: Dataset[WithSeq] = spark.sqlContext.createDataFrame[WithSeq](List(WithSeq(List("1")))).as[WithSeq]
    df2.show()
    //hooray, it works! :)
    println(df2.rdd.count())
  }
}

答案 1 :(得分:0)

case class WithList(list: Seq [String])

列表是scala.collection。不可变。列表

Seq 是scala.collection.Seq