如何使用age age to age column在spark sql中工作

时间:2018-02-26 07:09:22

标签: scala apache-spark

我有以下代码:

  test("test $") {
    val spark = SparkSession.builder().enableHiveSupport().master("local").appName("$").getOrCreate()
    import spark.implicits._
    val df = Seq(("A", 1), ("B", 2), ("C", 3)).toDF("name", "age")
    df.select($"name").show()

    spark.stop()


  }

$中的$"name"在隐式类中定义:

  implicit class StringToColumn(val sc: StringContext) {
    def $(args: Any*): ColumnName = {
          new ColumnName(sc.s(args: _*))
    }
  }

使用此隐式类,为类StringContext定义$ method 以便以下代码是正确的:

val x = StringContext("Hello")
x.$("World")

我会问隐式转换在df.select($"name").show()

中是如何工作的

1 个答案:

答案 0 :(得分:1)

StringContext是Scala标准库的类:This class provides the basic mechanism to do String Interpolation,类似于

val name = "Jennie"
val statement = s"Her name is $name" // s actually is a method of StringContext that is used to insert its arguments between corresponding parts of the string context`

隐式课程StringToColumn是将$方法简化为StringContext课程。

implicit class StringToColumn(val sc: StringContext) {
    def $(args: Any*): ColumnName = {
          new ColumnName(sc.s(args: _*)) // call s method
    }
  }

假设select需要column类型的参数。调用select($"column_string"),scala编译器不会立即放弃,它会查找StringContextcolumn之间的隐式转换,并找出StringToColumn

更新s("Her name is $name")错误的原因。因为当scala编译器看到s"Her name is $name"它将重写为StringContext("Her name is ", "").s(name)时。如果您使用s("..."),编译器会将s视为String Interpolation的函数而不是指标。

您可以通过创建像test.scala

这样的虚拟标量文件来验证它
class A{
    val name = "Jennie"
    val a = s"Her name is $name"
}

然后使用scalac -print test.scala,它会在重写阶段后显示代码。

package <empty> {
  class A extends Object {
    private[this] val name: String = _;
    <stable> <accessor> def name(): String = A.this.name;
    private[this] val a: String = _;
    <stable> <accessor> def a(): String = A.this.a;
    def <init>(): A = {
      A.super.<init>();
      A.this.name = "Jennie";
      A.this.a = new StringContext(scala.Predef.wrapRefArray(Array[String]{"Her name is ", ""}.$asInstanceOf[Array[Object]]())).s(scala.Predef.genericWrapArray(Array[Object]{A.this.name()}));
      ()
    }
  }
}