将 rdd 映射到空值上的 java 语音匹配库时,Spark 抛出 java.lang.NullPointerException
Posted
技术标签:
【中文标题】将 rdd 映射到空值上的 java 语音匹配库时,Spark 抛出 java.lang.NullPointerException【英文标题】:Spark throws java.lang.NullPointerException when mapping rdd with java phonetic matching library on null values 【发布时间】:2017-04-07 02:12:51 【问题描述】:我有一个使用 map 从 DataFrame 转过来的 RDD:
case class Record(id_1: Int, fnam_1: String, lnam_1: String, id_2: Long, fnam_2: String, lnam_2: String)
val rdd = df.map
case Row(id_1: Int, fnam_1: String, lnam_1: String, id_2: Long, fnam_2: String, lnam_2: String) =>
Record(id_1, fnam_1, lnam_1, id_2, fnam_2, lnam_2)
然后我使用java音标匹配库对这个rdd进行过滤操作(如下图):
import edu.ualr.oyster.utilities.DoubleMetaphone
def matchFirstName(rec: Record) =
val s1 = Option(rec.fnam_1).getOrElse("")
val s2 = Option(rec.fnam_2).getOrElse("")
if (s1.isEmpty || s2.isEmpty)
false
else
new DoubleMetaphone().compareDoubleMetaphone(s1, s2)
val rdd_filtered = rdd.filter(matchFirstName(_))
当我运行这个时,我得到一个 NPE 错误:
17/04/06 19:06:31 WARN scheduler.TaskSetManager: Lost task 0.0 in stage 4.0 (TID 160, my.work.cluster.com): java.lang.NullPointerException
at edu.ualr.oyster.utilities.DoubleMetaphone.compareDoubleMetaphone(DoubleMetaphone.java:1020)
at funpackage.EntityResolution$.phoneticMatching(EntityResolution.scala:106)
at esurance.EntityResolution$.esurance$EntityResolution$$matchNames$1(EntityResolution.scala:118)
at esurance.EntityResolution$$anonfun$8.apply(EntityResolution.scala:137)
at esurance.EntityResolution$$anonfun$8.apply(EntityResolution.scala:137)
at scala.collection.Iterator$$anon$14.hasNext(Iterator.scala:390)
at scala.collection.Iterator$$anon$11.hasNext(Iterator.scala:327)
at scala.collection.Iterator$$anon$11.hasNext(Iterator.scala:327)
at scala.collection.Iterator$$anon$10.hasNext(Iterator.scala:308)
at scala.collection.Iterator$class.foreach(Iterator.scala:727)
at scala.collection.AbstractIterator.foreach(Iterator.scala:1157)
at scala.collection.generic.Growable$class.$plus$plus$eq(Growable.scala:48)
at scala.collection.mutable.ArrayBuffer.$plus$plus$eq(ArrayBuffer.scala:103)
at scala.collection.mutable.ArrayBuffer.$plus$plus$eq(ArrayBuffer.scala:47)
at scala.collection.TraversableOnce$class.to(TraversableOnce.scala:273)
at scala.collection.AbstractIterator.to(Iterator.scala:1157)
at scala.collection.TraversableOnce$class.toBuffer(TraversableOnce.scala:265)
at scala.collection.AbstractIterator.toBuffer(Iterator.scala:1157)
at scala.collection.TraversableOnce$class.toArray(TraversableOnce.scala:252)
at scala.collection.AbstractIterator.toArray(Iterator.scala:1157)
at org.apache.spark.sql.execution.SparkPlan$$anonfun$5.apply(SparkPlan.scala:215)
at org.apache.spark.sql.execution.SparkPlan$$anonfun$5.apply(SparkPlan.scala:215)
at org.apache.spark.SparkContext$$anonfun$runJob$5.apply(SparkContext.scala:1850)
at org.apache.spark.SparkContext$$anonfun$runJob$5.apply(SparkContext.scala:1850)
at org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:66)
at org.apache.spark.scheduler.Task.run(Task.scala:88)
at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:214)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
我尝试在项目中的一对字符串上使用语音匹配,它确实没有问题。我还在 spark sql 中使用了相同的库,包装在用户定义的函数中,没有任何问题。我怀疑问题可能是由于我的某些值可能丢失(null)这一事实引起的。但我试图用Option
来解决这个问题。知道为什么会失败吗?
【问题讨论】:
虽然 Scala 不是非常地道,但我看不出有什么明显的东西可以产生 NPE。您是否查看了s1
和 s2
的哪些值触发了异常?您是否查看了DoubleMetaphone
的第 120 行,看看那里发生了什么?例如,如果DoubleMetaphone
对产生null
的空字符串执行某些操作怎么办?我不是说这就是发生的事情,但我认为你有很多调查途径。
【参考方案1】:
我没有尝试深入研究edu.ualr.oyster
库以查看它是否导致异常。但似乎确实如此。我切换到使用org.apache.commons.codec.language
库(相同的双变音功能)并且程序在火花上运行没有问题。
【讨论】:
以上是关于将 rdd 映射到空值上的 java 语音匹配库时,Spark 抛出 java.lang.NullPointerException的主要内容,如果未能解决你的问题,请参考以下文章
bean 的初始化失败 SpelEvaluationException: EL1012E: 无法在 spring 批处理错误中索引到空值