我正在学习Apache Spark,并且正在使用Java 8和Spark Core 2.3.2。
我发现当我在RDD上使用map函数时,它仅在使用Lambda表达式时有效。
这可行:
JavaRDD<Integer> rdd = sc.parallelize(Arrays.asList(1, 2, 3, 4));
JavaRDD<Integer> result = rdd.map(x -> x*x );
但这不会,并引发org.apache.spark.SparkException:任务无法序列化
JavaRDD<Integer> result = rdd.map(new Function<Integer, Integer>() {
public Integer call(Integer x) { return x*x; }
});
有人可以解释为什么吗? 谢谢
答案 0 :(得分:1)
当您声明new Function
时,它包含对包含它的类的引用。当Spark尝试将新的匿名Function实例发送给工作程序时,它也尝试对包含的类进行序列化,但是显然,该类未实现Serializable或具有其他不可序列化的成员。您可能会遇到类似object not serializable (class: YourClass, value: YourClass@e49bf8a)
的错误,其中“ YourClass”是包含Function声明的类。
如果您改为将Function声明为类的静态成员,则:
static Function<Integer, Integer> f = new Function<Integer, Integer>() {
public Integer call(Integer x) {
return x * x;
}
};
并将其传递给您的map函数:
JavaRDD<Integer> result = rdd.map(f);
那么您可能会好起来的。我通常会尝试将要在此类转换中使用的所有函数声明为静态(如果它们太大而无法使用lambda形式),因此我不会在偶然的情况下意外地序列化整个类一个功能。