用于从行读取值的以下Scala(Spark 1.6)代码在值为null时失败并带有NullPointerException
。
val test = row.getAs[Int]("ColumnName").toString
虽然这很好
val test1 = row.getAs[Int]("ColumnName") // returns 0 for null
val test2 = test1.toString // converts to String fine
是什么导致NullPointerException
以及处理此类案件的推荐方法是什么?
PS:从DataFrame获取行如下:
val myRDD = myDF.repartition(partitions)
.mapPartitions{ rows =>
rows.flatMap{ row =>
functionWithRows(row) //has above logic to read null column which fails
}
}
functionWithRows
然后上面提到NullPointerException
。
MyDF架构:
root
|-- LDID: string (nullable = true)
|-- KTAG: string (nullable = true)
|-- ColumnName: integer (nullable = true)
getAs
定义为:
def getAs[T](i: Int): T = get(i).asInstanceOf[T]
当我们执行toString时,我们调用不依赖于类型的Object.toString
,因此编译器会删除asInstanceOf[T]
,即
row.getAs[Int](0).toString -> row.get(0).toString
我们可以通过编写一个简单的scala代码来确认:
import org.apache.spark.sql._
object Test {
val row = Row(null)
row.getAs[Int](0).toString
}
然后编译它:
$ scalac -classpath $SPARK_HOME/jars/'*' -print test.scala
[[syntax trees at end of cleanup]] // test.scala
package <empty> {
object Test extends Object {
private[this] val row: org.apache.spark.sql.Row = _;
<stable> <accessor> def row(): org.apache.spark.sql.Row = Test.this.row;
def <init>(): Test.type = {
Test.super.<init>();
Test.this.row = org.apache.spark.sql.Row.apply(scala.this.Predef.genericWrapArray(Array[Object]{null}));
Test.this.row().getAs(0).toString();
()
}
}
}
所以正确的方法是:
String.valueOf(row.getAs[Int](0))
为了避免空值,更好的做法是在检查之前使用isNullAt
,正如documentation建议的那样:
脆
<T> T getAs(int i)
返回位置
i
的值。对于原始类型,如果value为null,则返回特定于原语的“零值”,即。0
为Int
- 使用isNullAt
确保该值不为null
但我同意这种行为令人困惑。
• 无法读取未定义的属性(读取“订阅”)- React redux 工具包
• 在打字稿中读取配置时是否可以将对象的键作为动态字符串传递
• 无法从 com.android.aaptcompiler 中提取资源
• Goroutine 导致 EKS Pod 中出现分段错误
• 尝试在 zip 文件中并行处理每个单独的文件类型时出现文件头损坏错误
• 通过 REST API,从 Javascript 中的 Firebase 云函数中对 Firebase 实时数据库进行经过身份验证的浅层读取
• smtp.office365.com 发送邮件失败。无法从传输连接读取数据:net_io_connectionclosed
• DragNDrop Pan 库 -> 无法读取未定义的属性(读取“更新”);
• 日期/时间字段值超出范围:在 POSTGRESQL 中使用 \COPY 时出现“0000-00-00 00:00:00”
• 无法从 selenium java 中的 csv/excel 文件读取更新数据