簡體   English   中英

隱式類不適用於通用類型

[英]Implicit class not working for Generic Type

我正在嘗試使用隱式類來簡化將數據加載到配置單元表中(使用 Spark)

例如說:如果這是我的數據,

case class Name(name: String, age: Int)
val lst = List(Name("name1", 24), Name("name2", 25))

我想像這樣將數據加載到表lst.loadToTable(db = "somedb", table = "sometable")

這是我到目前為止使用Implicit class實現上述 ^ 所做的工作,

object TableHelper {

    implicit class TableUtil[X: ClassTag](lst: Seq[X]){

        def loadToTable(db: String, table: String)(implicit spark: SparkSession): Unit ={
            println("Table -> " + table)
            spark.catalog.tableExists(s"${db}.${table}") match {
                case true =>
                    println(s"Table exist. Not creating new one: $table")
                case false =>
                    println(s"Table DO NOT exist. Creating new one: $table")
                    // Create database
                    val ddl = s"CREATE DATABASE IF NOT EXISTS ${db}"
                    println("ddl -> " + ddl)
                    spark.sql(ddl)
                    // Create DataFrame
                    import spark.implicits._
                    val df = spark.sparkContext.parallelize(lst).toDF() // Compiler ERROR
                    // TODO: Pending: Create table & Load data
            }
        }

    }

}

問題是,我收到此編譯器錯誤,

Error:(27, 66) value toDF is not a member of org.apache.spark.rdd.RDD[X]
                    val df = spark.sparkContext.parallelize(lst).toDF()

問題似乎是toDF()在使用泛型類型時不起作用(在我的代碼中lstSeq[X] )。 知道需要做什么來糾正這個問題嗎?

最后我能夠修復代碼(不知道為什么我的問題被否決了。如果指定原因會更有意義)。 感謝@Worakarn Isaratham 的指導。 此處指定的內容相比,代碼需要進行一些額外的更改

import org.apache.spark.sql.SparkSession
import scala.reflect.ClassTag
import scala.reflect.runtime.universe._

object TableHelper {
    // FIX is X <: Product : ClassTag : TypeTag    
    implicit class TableUtil[X <: Product : ClassTag : TypeTag](lst: Seq[X]){

        def loadToTable(db: String, table: String)(implicit spark: SparkSession): Unit ={
            println("Table -> " + table)
            spark.catalog.tableExists(s"${db}.${table}") match {
                case true =>
                    println(s"Table exist. Not creating new one: $table")
                    // TODO: Pending: Load data    
                case false =>
                    println(s"Table DO NOT exist. Creating new one: $table")
                    // Create database
                    val ddl = s"CREATE DATABASE IF NOT EXISTS ${db}"
                    println("ddl -> " + ddl)
                    spark.sql(ddl)
                    // Create DataFrame
                    import spark.implicits._
                    val df = spark.sparkContext.parallelize(lst).toDF()
                    df.show(100, false)
                // TODO: Pending: Create table & Load data
            }
        }

    }

}

[X <: Product : ClassTag : TypeTag]成功了。 parallelize method需要ClassTag

  def parallelize[T: ClassTag](
      seq: Seq[T],
      numSlices: Int = defaultParallelism): RDD[T] = withScope {

X <: Product可能告訴...我將要使用的通用類型實現了Product特性(所有case class實現了Product

toDF方法需要toDF才能訪問已擦除的類型(在運行時)

...現在我可以像這樣簡化調用約定

val lst = List(Name("name1", 24), Name("name2", 25))
lst.loadToTable("somedb", "sometable")

這是結果

+-----+---+
|name |age|
+-----+---+
|name1|24 |
|name2|25 |
+-----+---+

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM