很简单的Spark Rdd操作,提示如下错误:
Error:(46, 15) 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", 30, "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:(24, 12) 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:(24, 12) could not find implicit value for parameter reads: Person[A]
convert("Hello, yiifaa")
Error:(24, 12) not enough arguments for method convert: (implicit reads: Person[A])Unit.
Unspecified value parameter reads.
convert("Hello, yiifaa")
正确的调用方法如下:
convert[Foo]("Hello, yiifaa")
结论
使用隐式参数时,当有多个隐式对象满足条件时,请明确指定隐式类型。