为什么要使用Spark Dataframe函数的参数(例如:groupby,select)被设计为类似于(col1:字符串,列:字符串 *)而不是(列数:字符串 *)?

r55awzrz  于 2023-03-19  发布在  Apache
关注(0)|答案(1)|浏览(93)

在Spark中,有一批操作符或函数,如“select”、“groupby”、“dropDuplicates ..."
这些函数的参数始终类似于(col1:字符串,列:字符串 *),例如:

@scala.annotation.varargs
  def dropDuplicates(col1: String, cols: String*): Dataset[T] = {
    val colNames: Seq[String] = col1 +: cols
    dropDuplicates(colNames)
  }

  @scala.annotation.varargs
  def groupBy(col1: String, cols: String*): RelationalGroupedDataset = {
    val colNames: Seq[String] = col1 +: cols
    RelationalGroupedDataset(
      toDF(), colNames.map(colName => resolve(colName)), RelationalGroupedDataset.GroupByType)
  }

  @scala.annotation.varargs
  def select(col: String, cols: String*): DataFrame = select((col +: cols).map(Column(_)) : _*)

当参数类型为字符串时,函数始终定义为(col:字符串,列:字符串 *)而不是(列数:字符串 *)。
在每个函数中,第一条语句总是将两个段落组合在一起,如“瓦尔colNames:序列[字符串] =列1+:cols”,没有别的了。

考虑到参数类型为列时只有一个参数,例如:

@scala.annotation.varargs
  def groupBy(cols: Column*): RelationalGroupedDataset = {
    RelationalGroupedDataset(toDF(), cols.map(_.expr), RelationalGroupedDataset.GroupByType)
  }

  @scala.annotation.varargs
  def select(cols: Column*): DataFrame = withPlan {
    Project(cols.map(_.named), logicalPlan)
  }

所以我想知道为什么不用(cols:字符串 *)而不是(第1列:字符串,列:字符串 *)?看起来像(cols:字符串 *)的含义更像(cols:栏 *)

zaqlnxep

zaqlnxep1#

这种做法可以追溯到Java。在Effective Java的第三版中,
Item53: Use varargs judiciously .
有时候,编写一个需要 * 一个 * 或多个某种类型的参数的方法是合适的,而不是 * 零个 * 或更多。假设你想写一个函数来计算它的参数的最小值。2如果客户端没有传递参数,这个函数就没有被很好地定义。3你可以在运行时检查数组的长度。4 [但是]这个解决方案有几个问题。最严重的问题是,如果客户端调用此方法时没有参数,则它会在运行时而不是编译时失败。
幸运的是,有一种更好的方法可以达到预期的效果。声明该方法接受两个参数,一个指定类型的normal参数和一个该类型的varargs参数。这种解决方案纠正了前一个解决方案的所有缺陷。
当然,这是假设你至少需要一个参数,如果你的函数可以使用零个参数,那么一个(varargs)参数就可以了。

相关问题