Java Spark CSV-未找到适用于实际参数的构造函数/方法

Java Spark CSV-未找到适用于实际参数的构造函数/方法,java,apache-spark,apache-spark-sql,apache-spark-dataset,Java,Apache Spark,Apache Spark Sql,Apache Spark Dataset,在java spark应用程序中,在类型化数据集的过滤器和映射上使用lambda函数有一个问题 我得到这个运行时错误 ERROR CodeGenerator: failed to compile: org.codehaus.commons.compiler.CompileException: File 'generated.java', Line 130, Column 126: No applicable constructor/method found for actual paramete

在java spark应用程序中,在类型化数据集的过滤器和映射上使用lambda函数有一个问题

我得到这个运行时错误

ERROR CodeGenerator: failed to compile: org.codehaus.commons.compiler.CompileException: File 'generated.java', Line 130, Column 126: No applicable constructor/method found for actual parameters "org.apache.spark.unsafe.types.UTF8String"; candidates are: "public static java.sql.Date org.apache.spark.sql.catalyst.util.DateTimeUtils.toJavaDate(int)"
我正在使用下面的类和spark 2.2.0。 中提供了完整的示例和示例数据

我使用这个命令来加载CSV文档

val cdr = spark.read.format("csv").option("header", "true").option("delimiter", ";").schema(cdrCSVSchema).csv("CDR_SAMPLE.csv")
然后尝试了这个命令来编码并运行lambda函数,但仍然出现了错误

cdr.as[CDR].filter(c => c.timestamp != null).show

TL;DR显式定义模式,因为输入数据集没有可用于推断类型的值(对于
java.sql.Date
字段)

对于您的情况,使用非类型化数据集API可能是一种解决方案(也许是一种解决方法,老实说,我建议使用它以避免从内部行格式进行不必要的反序列化):

(这是Scala,我将把它翻译成Java作为一个家庭练习)

问题在于,在输入
CDR_SAMPLE.csv
文件中使用
inferSchema
选项时,大多数字段不可用,这使得大多数字段的类型为String(当没有值可用于推断更具体的类型时,这是默认类型)

这使得
java.sql.Date
类型的字段,即
dateParam1
dateParam5
类型为String

import org.opencell.spark.model.CDR
import org.apache.spark.sql.Encoders
implicit val cdrEnc = Encoders.bean(classOf[CDR])
val cdrs = spark.read.
  option("inferSchema", "true").
  option("delimiter", ";").
  option("header", true).
  csv("/Users/jacek/dev/sandbox/test-bigdata/CDR_SAMPLE.csv")
scala> cdrs.printSchema
root
 |-- timestamp: timestamp (nullable = true)
 |-- quantity: integer (nullable = true)
 |-- access: string (nullable = true)
 |-- param1: string (nullable = true)
 |-- param2: string (nullable = true)
 |-- param3: string (nullable = true)
 |-- param4: string (nullable = true)
 |-- param5: string (nullable = true)
 |-- param6: string (nullable = true)
 |-- param7: string (nullable = true)
 |-- param8: string (nullable = true)
 |-- param9: string (nullable = true)
 |-- dateParam1: string (nullable = true)
 |-- dateParam2: string (nullable = true)
 |-- dateParam3: string (nullable = true)
 |-- dateParam4: string (nullable = true)
 |-- dateParam5: string (nullable = true)
 |-- decimalParam1: string (nullable = true)
 |-- decimalParam2: string (nullable = true)
 |-- decimalParam3: string (nullable = true)
 |-- decimalParam4: string (nullable = true)
 |-- decimalParam5: string (nullable = true)
 |-- extraParam: string (nullable = true)
请注意,感兴趣的字段,即
dateParam1
dateParam5
,都是字符串

 |-- dateParam1: string (nullable = true)
 |-- dateParam2: string (nullable = true)
 |-- dateParam3: string (nullable = true)
 |-- dateParam4: string (nullable = true)
 |-- dateParam5: string (nullable = true)
当您通过使用
CDR
类中定义的编码器“假装”字段类型不同时,问题就会出现,该类中规定:

private Date dateParam1;
private Date dateParam2;
private Date dateParam3; 
private Date dateParam4; 
private Date dateParam5; 
这是问题的根本原因。Spark能从课堂上推断出的东西是有区别的。如果没有转换,代码会工作,但既然你坚持

cdrs.as[CDR]. // <-- HERE is the issue = types don't match
  filter(cdr => cdr.timestamp != null).
  show // <-- trigger conversion
cdrs.as[CDR]//
 |-- dateParam1: string (nullable = true)
 |-- dateParam2: string (nullable = true)
 |-- dateParam3: string (nullable = true)
 |-- dateParam4: string (nullable = true)
 |-- dateParam5: string (nullable = true)
private Date dateParam1;
private Date dateParam2;
private Date dateParam3; 
private Date dateParam4; 
private Date dateParam5; 
cdrs.as[CDR]. // <-- HERE is the issue = types don't match
  filter(cdr => cdr.timestamp != null).
  show // <-- trigger conversion