如何有效地加入任意数量的RDD?

时间:2017-04-18 16:29:32

标签: java join apache-spark java-8

使用RDD1.join(RDD2)加入两个RDD非常简单。但是,如果我在List<JavaRDD>中保留任意数量的RDD,我该如何有效地加入它们?

2 个答案:

答案 0 :(得分:3)

首先,请注意您无法加入JavaRDD。您需要使用以下内容获取JavaPairRDD

  • groupBy()(或keyBy()
  • cartesian()
  • [flat]mapToPair()
  • zipWithIndex()(很有用,因为它添加索引,但没有)

然后,一旦你有了你的清单,就可以像这样加入他们:

JavaPairRDD<Integer, String> linesA = sc.parallelizePairs(Arrays.asList(
                                            new Tuple2<>(1, "a1"),
                                            new Tuple2<>(2, "a2"),
                                            new Tuple2<>(3, "a3"),
                                            new Tuple2<>(4, "a4")));
JavaPairRDD<Integer, String> linesB = sc.parallelizePairs(Arrays.asList(
                                            new Tuple2<>(1, "b1"),
                                            new Tuple2<>(5, "b5"),
                                            new Tuple2<>(3, "b3")));
JavaPairRDD<Integer, String> linesC = sc.parallelizePairs(Arrays.asList(
                                            new Tuple2<>(1, "c1"),
                                            new Tuple2<>(5, "c6"),
                                            new Tuple2<>(6, "c3")));

// the list of RDDs
List<JavaPairRDD<Integer, String>> allLines = Arrays.asList(linesA, linesB, linesC);

// since we probably don't want to modify any of the datasets in the list, we will
// copy the first one in a separate variable to keep the result
JavaPairRDD<Integer, String> res = allLines.get(0);
for (int i = 1; i < allLines.size(); ++i) {  // note we skip position 0 !
    res = res.join(allLines.get(i))
    /*[1]*/  .mapValues(tuple -> tuple._1 + ':' + tuple._2);
}

[1]行是重要的一行,因为它映射了

JavaPairRDD<Integer, Tuple2<String,String>>回到

JavaPairRdd<Integer,String>使其与其他联接兼容。

根据chrisw的回答,这可以像这样放入“一行”:

JavaPairRDD<Integer, String> res;
res = allLines.stream()
              .reduce((rdd1, rdd2) -> rdd1.join(rdd2).mapValues(tup -> tup._1 + ':' + tup._2))
              .get();  // get value from Optional<JavaPairRDD>

最后,关于表现的一些想法。在上面的示例中,我使用字符串连接将连接的结果减少回相同类型的RDD。如果你有很多RDD,你可以使用for loop版本JavaPairRDD<Integer, StringBuilder> res来加快速度,你可以手动进行第一次加入。如果需要,我会发布更多细节。

答案 1 :(得分:1)

我不熟悉JavaRDD类/接口,但您可以使用Java 8中的高阶函数reduce解决此问题,请参阅https://docs.oracle.com/javase/tutorial/collections/streams/reduction.html

final List<JavaRDD> list = getList(); // where getList is your list implementation containing JavaRDD instances

// The JavaRDD class provides rdd() to get the RDD
final JavaRDD rdd = list.stream().map(JavaRDD::rdd).reduce(RDD::join);

String类的示例如下: -

Stream.of("foo", "bar", "baz").reduce(String::concat);

哪个产生

  

foobarbaz