我需要使用Scala Spark过滤器的测试器,测试器实现java的Predicate接口并通过参数接收特定的类名。 我正在做这样的事情
val tester = Class.forName(qualifiedName).newInstance().asInstanceOf[Predicate[T]]
var filtered = rdd.filter(elem => tester.test(elem))
问题是在运行时我有一个Spark“TaskNotSerializable Exception”,因为我的特定Predicate类不是Serializable。
如果我这样做
val tester = Class.forName(qualifiedName).newInstance()
.asInstanceOf[Predicate[T] with Serializable]
var filtered = rdd.filter(elem => tester.test(elem))
我得到了同样的错误。 如果我在rdd.filter中创建测试程序,它就会起作用:
var filtered = rdd.filter { elem =>
val tester = Class.forName(qualifiedName).newInstance()
.asInstanceOf[Predicate[T] with Serializable]
tester.test(elem)
}
但我会创建一个对象(可能是广播)进行测试。我该如何解决?
答案 0 :(得分:0)
您只需要要求类实现Serializable
。请注意,asInstanceOf[Predicate[T] with Serializable]
强制转换是谎言:它实际上并不检查值是Serializable
,这就是为什么第二种情况不会在演员表中立即产生错误,而最后一个“成功” ”
但我会创建一个对象(可能是广播)进行测试。
你做不到。是否广播,反序列化将在工作节点上创建 new 对象。但是,您只能在每个分区上创建一个实例:
var filtered = rdd.mapPartitions { iter =>
val tester = Class.forName(qualifiedName).newInstance()
.asInstanceOf[Predicate[T]]
iter.filter(tester.test)
}
它实际上比序列化tester
,发送它和反序列化更好,因为它的工作量非常少。