在测试中,我尝试将Dataframe/数据集转换为集合并进行比较。例如
actualResult.collect.toSet should be(expectedResult.collect.toSet)
我注意到一些关于 Double.NaN
价值观。
在斯卡拉, Double.NaN == Double.NaN
返回false。
Spark NaN == NaN
这是真的(官方文件)
但我不明白为什么dataframe和dataset的行为不同。
import org.apache.spark.sql.SparkSession
object Main extends App {
val spark = SparkSession.builder().appName("Example").master("local").getOrCreate()
import spark.implicits._
val dataSet = spark.createDataset(Seq(Book("book 1", Double.NaN)))
// Compare Set(Book(book 1,NaN)) to itself
println(dataSet.collect.toSet == dataSet.collect.toSet) //false, why?
// Compare Set([book 1,NaN]) to itself
println(dataSet.toDF().collect.toSet == dataSet.toDF().collect.toSet) //true, why?
}
case class Book (title: String, price: Double)
这是我的问题。感谢你的真知灼见。
它是如何在代码中发生的(在哪里 equals
是否被覆盖?等等…)
这种设计背后有什么原因吗?有没有更好的范例在测试中Assert数据集/Dataframe?
1条答案
按热度按时间p8ekf7hl1#
我有几点想和大家分享。
当你这么做的时候
dataSet.collect.toSet
当你在两组图书对象之间进行比较时,你把它收集为set[book]。单个(book)objects equal方法用于在book case类中定义的比较。这就是为什么
println(dataSet.collect.toSet == dataSet.collect.toSet)
返回false是因为Double.NaN == Double.NaN returns false
.当你这么做的时候
dataSet.toDF().collect.toSet
按集合[行]收集当您执行todf时,spark将转换**(即序列化book,然后反序列化为javatype fields row)**book类到row在这个过程中,它还使用行编码器对字段进行一些转换。
使用rowcoder.scala中的以下代码将所有原语字段转换为java类型
如果您检查double.java和float.java equal方法的源代码。比较一下楠就会变成真的。这就是为什么行对象比较将返回true。以及
println(dataSet.toDF().collect.toSet == dataSet.toDF().collect.toSet)
这是真的。**抱歉,如果我的语法错了。