You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spark Scala字符串匹配自定义UDF运行空指针异常问题排查

Spark Scala自定义UDF空指针异常问题解决

问题复现

编写如下字符串匹配UDF代码:

import org.apache.spark.sql.functions.lit

val containsString  = (haystack:String, needle:String) =>{
    if (haystack.contains(needle)){
        1
    }
    else{
         0
    }
}

val containsStringUDF = udf(containsString _)

// 原代码存在括号书写笔误,已修正参数位置
val new_df = df.withColumn("nameContainsxyz", containsStringUDF($"name", lit("xyz")))

代码编译通过,但执行聚合查询时抛出错误:

new_df.groupBy("nameContainsxyz").sum().show()

报错堆栈信息如下:

Caused by: org.apache.spark.SparkException: Failed to execute user defined function($anonfun$1: (string, string) => int)
  at org.apache.spark.sql.catalyst.expressions.GeneratedClass$GeneratedIteratorForCodegenStage6.agg_doAggregateWithKeys_0$(Unknown Source)
  at org.apache.spark.sql.catalyst.expressions.GeneratedClass$GeneratedIteratorForCodegenStage6.processNext(Unknown Source)
  at org.apache.spark.sql.execution.BufferedRowIterator.hasNext(BufferedRowIterator.java:43)
  at org.apache.spark.sql.execution.WholeStageCodegenExec$$anonfun$15$$anon$2.hasNext(WholeStageCodegenExec.scala:655)
  at scala.collection.Iterator$$anon$11.hasNext(Iterator.scala:409)
  at org.apache.spark.shuffle.sort.BypassMergeSortShuffleWriter.write(BypassMergeSortShuffleWriter.java:125)
  at org.apache.spark.scheduler.ShuffleMapTask.runTask(ShuffleMapTask.scala:99)
  at org.apache.spark.scheduler.ShuffleMapTask.runTask(ShuffleMapTask.scala:55)
  at org.apache.spark.scheduler.Task.run(Task.scala:121)
  at org.apache.spark.executor.Executor$TaskRunner$$anonfun$10.apply(Executor.scala:408)
  at org.apache.spark.util.Utils$.tryWithSafeFinally(Utils.scala:1405)
  at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:414)
  ... 3 more
Caused by: java.lang.NullPointerException
  at $anonfun$1.apply(<console>:41)
  at $anonfun$1.apply(<console>:40)
  ... 15 more

根因分析

Spark DataFrame的字符串列允许存储null值,当UDF处理的name列存在null值时,null会被传入UDF赋值给haystack参数,此时调用haystack.contains(needle)方法会直接触发空指针异常。

修复方案

在UDF逻辑中新增空值校验即可解决问题,修改后的UDF代码如下:

val containsString  = (haystack:String, needle:String) =>{
    // 空值场景默认返回0,可根据业务需求调整返回逻辑
    if (haystack == null || needle == null) {
        0
    } else if (haystack.contains(needle)) {
        1
    } else {
        0
    }
}

也可以直接使用Spark原生内置函数实现相同逻辑,避免自定义UDF的性能开销:

import org.apache.spark.sql.functions.{instr, when}
val new_df = df.withColumn("nameContainsxyz", when(instr($"name", "xyz") > 0, 1).otherwise(0))

内容的提问来源于stack exchange,提问作者Jin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 05:54:03