我在Spark 2.2中遇到了一些奇怪的事情,以及它如何反序列化case类。对于这些示例,假定该案例类:
TreeMap<Date, Double> sum =
list.stream()
.collect(Collectors.groupingBy(Payment::getDate,
TreeMap::new,
Collectors.summingDouble(Payment::getAmount)
)
);
如果执行以下映射操作,则在执行程序日志中同时看到我的构造函数和'a'消息的值。
case class X(a:Int, b:Int) {
println("in the constructor!!!")
}
通过以下映射操作,我看不到构造函数消息,但在执行程序日志中确实看到了“ a”消息的值。构造函数消息在驱动程序日志中。
ds.map(x => {
val x = X(1, 2)
println(s"a=${x.a})
}
如果我使用广播变量,也会得到相同的行为。
val x = X(1, 2)
ds.map(x => println(s"a=${x.a}"))
知道发生了什么吗? Spark是否根据需要序列化每个字段?我本来希望将整个对象运送过来并反序列化。有了这种反序列化,我期望有一个构造函数调用。
当我查看Products的编码器代码时,看起来好像它从构造函数中获取了必填字段。我猜我以为它会在这些东西上使用那些编码器。
我什至反编译了case类的类文件,并且生成的构造函数似乎很合理。
答案 0 :(得分:0)
Spark默认情况下使用Java序列化(之所以可用,是因为案例类扩展了Serializable
),它不需要使用构造函数来反序列化。参见this StackOverflow question for details on Java serialization/deserialization。
请注意,这种对Java序列化的依赖可能会导致问题,因为内部序列化格式没有固定设置,因此JVM版本差异可能导致反序列化失败。