为什么 dataset 的 foreach 方法不需要编码器,而 map 需要?

Why doesn't dataset's foreach method require an encoder, but map does?

我有两个数据集:Dataset[User]Dataset[Book],其中 UserBook 都是大小写 类。我这样加入他们:

val joinDS = ds1.join(ds2, "userid")

如果我尝试 map 遍历 joinDS 中的每个元素,编译器会抱怨缺少编码器:

not enough arguments for method map: (implicit evidence: org.apache.spark.sql.Encoder[Unit])org.apache.spark.sql.Dataset[Unit]. Unspecified value parameter evidence. Unable to find encoder for type stored in a Dataset.

但是如果我使用 foreach 而不是 map 就不会出现同样的错误。为什么 foreach 不需要编码器?我已经从 spark 会话中导入了所有隐含函数,那么为什么 map 根本不需要编码器,当数据集是连接两个包含 case 类) 的数据集的结果时?另外,我从该连接中获得什么类型的数据集?是 Dataset[Row] 还是其他什么?

TL;DR Encoder 需要将结果转换为内部 Spark SQL 格式,如果 foreach(或任何其他接收器)。

看看签名就知道了。 map

def map[U](func: (T) ⇒ U)(implicit arg0: Encoder[U]): Dataset[U] 

所以简单来说,它将记录从 T 转换为 U,然后使用 UEncoder 将结果转换为内部表示。

foreach 从另一方面来说,是

def foreach(f: (T) ⇒ Unit): Unit 

换句话说,它不期望任何结果。由于没有要存储的结果,Encoder 只是过时的。