如何在java Spark中组合两个RDD和不同的键?

时间:2015-11-11 15:43:03

标签: java apache-spark

假设我有一个Tuple2的RDD,如下所示:

<session1_w1, <0.2, 2>>, 
<session1_w2, <1.3, 4>>, 
<session1_w3, <0.4, 3>>, 
<session2_w1, <0.5, 2>>, 
<session2_w2, <2.3, 6>>

我需要将它映射到下面的RDD,这样最后一个字段是具有相同部分键值的元组的最后字段的总和,例如session1

2 + 4 + 3 => 9   
2 + 6 => 8

所以我期望的结果是:

<session1_w1, 0.2, 9>, 
<session1_w2, 1.3, 9>, 
<session1_w3, 0.4, 9>, 
<session2_w1, <0.5, 8>>, 
<session2_w2, <2.3, 8>>

这是某种减少,但我不想丢失原来的密钥。

我可以通过映射计算求和,然后缩减到下面的RDD,但是我需要将这个RDD与第一个RDD合并以获得结果。

<session1, 9> <session2, 8>

有什么想法吗?

1 个答案:

答案 0 :(得分:2)

您使用保留RDD结构的groupBy(但不保留订单,因此如果您想保存订单,则必须zipWithIndex以及之后sortBy索引)。

否则,如果你有RDD[(String,(Double,Int))]

// This should give you an RDD[(Iterative(String,Double),Int)]
val group = myRDD.groupBy(_._1).map(x => (x._2.map(y => (y._1,y._2._1)),
                                          x._2.map(y => y._2._2).reduce(_+_))) 

// This will give you back your RDD of [Summed Int, String, Double] which you can then map.
val result = group.map(x => (x._2,x._1)).flatMapValues(x => x)

你也可以做一个简单的reduceByKey(没有Double),然后将它连接回原始的RDD,这样就可以保留原来的双打。

========== EDIT ============

第二个连接解决方​​案只使用RDD连接。您的原始RDD格式为RDD[(String,(Double,Int))],我假设您已经获得了[(String,Int)]的RDD,其中String是会话,Int是总和。连接操作只是:

RDDOriginal.join(RDDwithSum).map(x=>(x._1,x._2._1._1,x._2._2)) // This should give you the Session (String) followed by the Double and the Int (the sum).

join方法也不保留顺序,如果要保留顺序,则必须执行zipWithIndex。