在下面的代码中,我试图合并值:
val rdd: org.apache.spark.rdd.RDD[((String), Double)] =
sc.parallelize(List(
(("a"), 1.0),
(("a"), 3.0),
(("a"), 2.0)
))
val reduceByKey = rdd.reduceByKey((a , b) => String.valueOf(a) + String.valueOf(b))
reduceByValue
应包含(a,1,3,2)但接收编译时错误:
Multiple markers at this line - type mismatch; found : String required: Double - type mismatch; found : String
required: Double
什么决定了reduce函数的类型?可以转换类型吗?
我可以使用groupByKey
来获得相同的结果,但只想了解reduceByKey
。
答案 0 :(得分:7)
不,给定RDD[(K,V)]
类型的rdd,reduceByKey
将采用类型为(V,V) => V
的关联函数。
如果我们想要应用将值类型更改为其他任意类型的缩减,那么我们可以使用aggregateByKey
:
def aggregateByKey[U](zeroValue: U)(seqOp: (U, V) ⇒ U, combOp: (U, U) ⇒ U)
使用zeroValue
和seqOp
函数,它在地图一侧提供类似折叠的操作,而关联函数combOp
将seqOp
的结果组合在一起最后的结果,就像reduceByKey一样。
我们可以从签名中理解,虽然集合值的类型为V
,但aggregateByKey
的结果将是任意类型U
应用于上面的示例,aggregateByKey
将如下所示:
rdd.aggregateByKey("")({case (aggr , value) => aggr + String.valueOf(value)}, (aggr1, aggr2) => aggr1 + aggr2)
答案 1 :(得分:1)
您的代码存在的问题是您的值类型不匹配。如果您更改了RDD中的值类型,则可以使用reduceByKey实现相同的输出。
val rdd: org.apache.spark.rdd.RDD[((String), String)] =
sc.parallelize(List(
("a", "1.0"),
("a", "3.0"),
("a", "2.0")
))
val reduceByKey = rdd.reduceByKey((a , b) => a.concat(b))
这是相同的例子。只要传递给reduceByKey的函数接受Value类型的两个参数(在你的情况下为Double)并返回相同类型的单个参数,你的reduceByKey就可以工作。