如何在Row上使用空值进行模式匹配?

时间:2017-10-26 06:49:43

标签: scala apache-spark

我想知道为什么我不能在包含空值(字符串)的Spark(2.1)行上进行模式匹配:

val r = Row(null:String)

r match {case Row(s:String) => println("row is null")}
  

scala.MatchError:[null](类   org.apache.spark.sql.catalyst.expressions.GenericRow)

2 个答案:

答案 0 :(得分:8)

Row在这里并没有发挥重要作用,我们可以简化:

val r = null: String

r match {case s:String => println("s is null")}

您可以检查模式匹配是否仍然失败。这是因为s: String等类型模式是specifically defined not to match null

  

类型模式T具有以下形式之一:

     
      
  • 对C,p.C或T#C类的引用。此类型模式匹配给定类的任何非空实例 ...
  •   

isInstanceOf的行为也是这样的:null.isInstanceOf[String]false

因此,如果您想匹配null,您可以

1)准确使用null作为模式:

r match {
  case s: String => println("r is not null")
  case null => println("r is null")
}

2)使用像_这样的“全能”模式或变量:

r match {
  case s: String => println("r is not null")
  case s => println("matches only if r is null or not a String")
}

或者如果我们放回Row,你就会写

r match {
  case Row(s: String) => println("r contains non-null")
  case Row(null) => println("r contains null")
}

答案 1 :(得分:0)

你可以,但模式应该完全匹配Row(null)

scala> r match { case Row(null) => "matched" }
res1: String = matched

你是对的,更通用的模式不起作用。

scala> r match { case Row(s: String) => "matched" }
scala.MatchError: [null] (of class org.apache.spark.sql.catalyst.expressions.GenericRow)
  ... 50 elided

认为这是因为null会给你Any类型来匹配(并且涉及某种类型的魔法我无法准确解释)。

scala> Row.unapplySeq(r)
res2: Some[Seq[Any]] = Some(WrappedArray(null))