【问题标题】:overloaded methods in Trait error Spark ScalaTrait 错误 Spark Scala 中的重载方法
【发布时间】:2020-05-18 15:28:16
【问题描述】:

我有一些代码

trait Reader {
  def read(spark: SparkSession, format: String, path: String): DataFrame
  def read[T: Encoder](spark: SparkSession, format: String, path: String): Dataset[T]
}

class LocalReader extends Reader {

  override def read[T: Encoder](spark: SparkSession, format: String, path: String): Dataset[T] = {
    spark.read
      .format(format)
      .option("header", "true")
      .load(getClass.getResource(path).getPath)
      .as[T]
  }

  override def read(spark: SparkSession, format: String, path: String): DataFrame = {
    spark.read
      .format(format)
      .option("header", "true")
      .load(getClass.getResource(path).getPath)
  }
}


object TopNSimilarCustomers extends SparkJob {
  override def appName: String = "TopNSimilarCustomers"

  override def run(spark: SparkSession, args: Array[String], reader: Reader): Unit = {

    /**
      * Only I/O here
      */

    if (args.length == 0)
      return
    val rawData = reader.read(spark, "json", "/spark-test-data.json")
    val res     = transform(spark, rawData, args(0))

  }

val rawData = reader.read(spark, "json", "/spark-test-data.json") 出现错误,无法解析重载方法读取。

所以我想拥有用于不同目的的 Readers/Writers LocalReader/S3Reader,因为它可以返回 DF 和 DS,所以我编写了一个重载方法,即使我必须使用一个。最终,必须同时实施。有什么办法可以避免吗?

我怎样才能实现我想要做的事情?任何其他方式或更好的方式等? 如何修复错误?

【问题讨论】:

  • 您只给它 2 个参数,而它还需要一个 SparkSession 对象。另外,您为什么不直接重命名您的方法,而不是让其中两个具有相同的签名?
  • 抱歉,错字,已更新。它仍然给出相同的错误
  • 尝试将您的 2 个读取方法重命名为 readDataFramereadDataSet 之类的名称
  • trait 中不需要两个签名相同的方法,执行两次即可
  • @Sam,实际上,他们这样做了。类型参数不算

标签: java scala apache-spark overloading


【解决方案1】:

获得cannot resolve overloaded method read. 的原因是Reader trait 有两种方法都将采用相同数量的参数。

要解决此问题,请重命名方法名称,例如 readDF & readDS,或者您也可以检查以下代码并根据您的要求进行修改。

    case class ReadConfig(format: String,path: String,options: Map[String,String])
    case class WriteConfig(format: String,path: String,options: Map[String,String])
    case class Config(read: ReadConfig,write: WriteConfig)

    trait Writer {
      def write(df: DataFrame): Unit
    }
    trait Reader {
      def read: DataFrame
    }

    trait RW extends Reader with Writer {
      val spark : SparkSession
      val config : Config
    }

    // Add logic for Local
    class Local(override val spark: SparkSession,override val config: Config) extends RW {
      override def read: DataFrame = {
        spark.read
          .format(config.read.format)
          .options(config.read.options)
          .load(config.read.path)
      }
      override def write(df: DataFrame): Unit = {
        df.write
          .format(config.write.format)
          .options(config.write.options)
          .save(config.write.path)
      }
    }

// Add logic for S3
 class S3(override val spark: SparkSession,override val config: Config) extends RW {
      override def read: DataFrame = {
        spark.read
          .format(config.read.format)
          .options(config.read.options)
          .load(config.read.path)
      }
      override def write(df: DataFrame): Unit = {
        df.write
          .format(config.write.format)
          .options(config.write.options)
          .save(config.write.path)
      }
    }

【讨论】:

  • 非常感谢。我喜欢这个主意。我对作家有类似的想法,或者像存储/ IO 之类的东西都可以。我会尽快实施。这是我的第一个 spark 应用程序/项目:D
  • 创建对象后无法更新配置。如果我想在工作期间在两个不同的位置或不同的格式写作怎么办?每次都必须创建一个新对象
  • 是的,我明白这一点,但我认为与其将它们设为 var,不如将它们放入读/写的参数中,或者单独或配置更好。你怎么看?
  • 读取函数需要两个,写入一个主要的东西。位置和格式。休息是可选的,因此可选的可以进入地图。当简单的参数起作用时,无需编写额外的代码。
  • 如果你问我我不会把逻辑写入两个不同的位置,那个代码不是通用的,你的代码将是写入数据序列模式。而是创建两个具有不同值的对象并并行调用 write 方法..想想这个..
猜你喜欢
  • 2014-10-09
  • 2020-08-15
  • 2013-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-15
  • 1970-01-01
相关资源
最近更新 更多