天天看点

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")
           

结论

使用隐式参数时,当有多个隐式对象满足条件时,请明确指定隐式类型。

继续阅读