天天看點

Spark:flatmap函數提示“ambiguous implicit values”的解決辦法

很簡單的Spark Rdd操作,提示如下錯誤:

Error:(, ) ambiguous implicit values:
 both method newIntEncoder in class SQLImplicits of type => org.apache.spark.sql.Encoder[Int]
 and method newLongEncoder in class SQLImplicits of type => org.apache.spark.sql.Encoder[Long]
 match expected type org.apache.spark.sql.Encoder[U]
      .flatMap((line: String) => {
           

看錯誤堆棧,提示有多個方法滿足匿名參數,而編譯器自身無法确定需要的類型。

是以解決辦法很簡單,明确地指定flatmap函數的泛型參數即可,下面以字元串為例:

//  明确指定泛型
rdd.flatMap[String]((line: String) => {
    //  傳回的資料必須是Seq,包含0到多條資料
    Seq(line)
})
           

從上面的例子可以看出,flapMap[A]的泛型參數必須與傳回資料Seq[A]的泛型參數相同,再看一例:

rdd.flatMap[Tuple3[String, Int, String]]((line: String) => {
    //  傳回類型是元組
    Seq(Tuple3("yiifaa", , "well"))
})
           

擴充

下面的例子仿照flatmap的設計方式與調用方式。

case class Foo(baz: String)
case class Bar(baz: String)
//  測試類
case class Person[A]() {

    def say(s : String): Unit = {
      println(s);
    }

}
//  引入泛型參數
def convert[A](s: String)(implicit reads: Person[A]): Unit = reads.say(s)
//  聲明多個隐式變量
implicit val fooReads = new Person[Foo]
implicit val barReads = new Person[Bar]
           

如果直接調用“convert(“Hello, yiifaa”)”方法,則提示類似的錯誤:

Error:(, ) ambiguous implicit values:
 both value barReads of type Person[Bar]
 and value fooReads of type Person[Foo]
 match expected type Person[A]
    convert("Hello, yiifaa")
Error:(, ) could not find implicit value for parameter reads: Person[A]
    convert("Hello, yiifaa")
Error:(, ) not enough arguments for method convert: (implicit reads: Person[A])Unit.
Unspecified value parameter reads.
    convert("Hello, yiifaa")
           

正确的調用方法如下:

convert[Foo]("Hello, yiifaa")
           

結論

使用隐式參數時,當有多個隐式對象滿足條件時,請明确指定隐式類型。

繼續閱讀