Java Spark CSV-未找到适用于实际参数的构造函数/方法
在java spark应用程序中,在类型化数据集的过滤器和映射上使用lambda函数有一个问题 我得到这个运行时错误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
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