如何通过左键和右值组合两个JavaPairRDD

时间:2015-05-17 23:42:21

标签: java join apache-spark

JavaPairRDD<字符串,长>之一:

  

[(A,0),(B,0),(C,0),(D,0),(E,0)...]

JavaPairRDD<字符串,长>二:

  

[(B,1),(C,5),(D,21)]

输出应该是:

  

[(A,0),(B,1),(C,5),(D,21),(E,0)...]

要使用基于第一个rdd, aggregateByKey union join (左或右)方法的键的第二个rdd值,请尝试使用但是没有用。

JavaPairRDD<String, Object> currentRdd = firstRdd.fullOuterJoin(secondRdd).map(stringTuple2Tuple2 -> new Tuple2<String, Long>(stringTuple2Tuple2._1(), stringTuple2Tuple2._2()._2().get()));

我如何组合这样的两个JavaPairRDD?

3 个答案:

答案 0 :(得分:2)

如果您希望firstRdd中的所有键都显示在最终结果中,或者您只是不关心仅出现在secondRdd中的键,则应使用 leftOuterJoin代替fullOuterJoin

leftOuterJoin解释:

  

执行thisother的左外连接。对于this中的每个元素(k,v),得到的RDD将包含other中w的所有对(k,(v,Some(w))),或者对(k, (v,无))如果other中的元素没有密钥k。

Scala版本:

val left = sc.parallelize(Array(("A", 0), ("B", 0), ("C", 0),("D", 0),("E", 0)))
val right = sc.parallelize(Array(("B", 1), ("C", 5), ("D", 21)))
val lojoin: RDD[(String, (Int, Option[Int]))] = left.leftOuterJoin(right)
val target = lojoin.mapValues(p => p._2.getOrElse(p._1))
target.foreach(println)

Java版本:

List<Tuple2<String, Integer>> left = new ArrayList<Tuple2<String, Integer>>();
left.add(new Tuple2<String, Integer>("A", 0));
left.add(new Tuple2<String, Integer>("B", 0));
left.add(new Tuple2<String, Integer>("C", 0));
left.add(new Tuple2<String, Integer>("D", 0));
left.add(new Tuple2<String, Integer>("E", 0));

List<Tuple2<String, Integer>> right = new ArrayList<Tuple2<String, Integer>>();
right.add(new Tuple2<String, Integer>("B", 1));
right.add(new Tuple2<String, Integer>("C", 5));
right.add(new Tuple2<String, Integer>("D", 21));

JavaPairRDD<String, Integer> leftRdd = sc.parallelizePairs(left);
JavaPairRDD<String, Integer> rightRdd = sc.parallelizePairs(right);

JavaPairRDD<String, Tuple2<Integer, Optional<Integer>>> lojRdd = leftRdd.leftOuterJoin(rightRdd);

JavaPairRDD<String, Integer> result = lojRdd.mapValues(new Function<Tuple2<Integer, Optional<Integer>>, Integer>() {
  @Override
  public Integer call(Tuple2<Integer, Optional<Integer>> v1) throws Exception {
    return v1._2().or(v1._1());
  }
});

result.foreach(new VoidFunction<Tuple2<String, Integer>>() {
  @Override
  public void call(Tuple2<String, Integer> t) throws Exception {
    System.out.println(t._1() + " " + t._2());
  }
});

答案 1 :(得分:1)

根据我的理解要求: 您有2个相同结构的RDD(例如:Id STR,值INT)。您需要所有ID(来自两个RDD)和值Summed。

下一部分假定此要求是正确的。如果没有,请不要费心阅读,而是用正确的要求留下评论:)

这就是我的建议:

  1. Union RDD1和RDD2(最好两者都应该基于ID进行类似的分区,所以这里不需要随机播放)
  2. 将联合RDD转换为dataFrame并将其注册为表(例如,T)
  3. 写&#34;通过id&#34;从T组中选择id,sum(value);
  4. 这会奏效。事实上,当我们将多个源与类似的结构组合在一起时,它是在RDBMS世界中加载数据的经过试验和测试的过程。

答案 2 :(得分:1)

您想要的实际上是一个 union ,后跟一个求和 reduceByKey 功能。

JavaPairRDD< String, Long> result = one.union(two).reduceByKey((x, y) -> x+y);

有关这些功能,请参阅文档。 https://spark.apache.org/docs/2.0.1/api/java/org/apache/spark/api/java/JavaPairRDD.html