使用reduceByKey时scala中的类型不匹配

时间:2018-05-03 12:31:39

标签: scala apache-spark

我已经在scala shell中单独测试了我的错误代码

scala> val p6 = sc.parallelize(List( ("a","b"),("b","c")))
p6: org.apache.spark.rdd.RDD[(String, String)] = ParallelCollectionRDD[10] at parallelize at <console>:24

scala> val p7 = p6.map(a => ((a._1+a._2), (a._1, a._2, 1)))
p7: org.apache.spark.rdd.RDD[(String, (String, String, Int))] = MapPartitionsRDD[11] at map at <console>:26

scala> val p8 = p7.reduceByKey( (a,b) => (a._1,(a._2, a._3+b._3)))
<console>:28: error: type mismatch;
 found   : (String, (String, Int))
 required: (String, String, Int)
       val p8 = p7.reduceByKey( (a,b) => (a._1,(a._2, a._3+b._3)))

我想使用a._1作为密钥,以便我可以进一步使用join运算符,并且它必须是(键,值)对。但我的问题是,为什么在使用减少功能时有required类型?我认为这种格式是由我们自己设定的,而不是规定的。我错了吗?

另外,如果我错了,那么为什么需要(String, String, Int)?为什么它不是别的什么?

ps:我知道(String, String, Int)(a._1+a._2), (a._1, a._2, 1))中的值类型,它是map函数,但官方示例显示reduce函数(a, b) => (a._1 + b._1, a._2 + b._2)是有效的。我认为所有这些,包括我上面的代码都应该是有效的

2 个答案:

答案 0 :(得分:2)

看一下类型。按键减少是RDD[(K, V)]上带签名的方法:

def reduceByKey(func: (V, V) ⇒ V): RDD[(K, V)]

换句话说,输入参数和返回参数必须属于同一类型。

在你的情况下p7

RDD[(String, (String, String, Int))]

其中KStringV(String, String, Int),因此reduceByKey使用的函数必须为

((String, String, Int), (String, String, Int)) => (String, String, Int)

有效的功能是:

p7.reduceByKey( (a,b) => (a._1, a._2, a._3 + b._3))

会给你

(bc,(b,c,1))
(ab,(a,b,1))

结果。

如果您想更改byKey方法中的类型,则必须使用aggregateByKeycombineByKey

答案 1 :(得分:1)

您的p7属于p7: org.apache.spark.rdd.RDD[(String, (String, String, Int))],但在reduceByKey您使用的(a._1,(a._2, a._3+b._3))类型为(String, (String, Int))

p8的输出类型也应为p8: org.apache.spark.rdd.RDD[(String, (String, String, Int))]

所以如下定义应该对你有用

val p8 = p7.reduceByKey( (a,b) => (a._1, a._2, a._3+b._3))

您可以阅读my answer in pyspark了解有关reduceByKey如何工作的更多详细信息

this one should help too