将RDD转换为键值对RDD,其值在List中

时间:2016-07-10 18:58:55

标签: java apache-spark rdd keyvaluepair

我有一个pairRDD,元组的格式如下:

for(int i = 0; i < arr.length; i++) {
    System.out.println("element of aray is "+ arr[i]); // It prints the element itself -> 11 12 13 14 15.. and so on
    System.out.println("iteration number "+ i); // It prints the index of iteration -> 0 1 2 3 4 5.. and so on
}     

我想要的是将上面的内容转换为键值对RDD,其中第一个字段是键,第二个字段是字符串列表(值)。即我想把它变成以下形式:

[(1,"b1","c1","d1","e1"), (2,"b2","c2","d2","e2"), ...

在此之后,是否可以访问我想要的任何字段?

例如,我可以访问元组[(1,["b1","c1","d1","e1"]), (2,["b2","c2","d2","e2"]), ... ,然后只提取字段(1,["b1","c1","d1","e1"])吗?

2 个答案:

答案 0 :(得分:3)

如果您有一个带有元组的RDD,但是代表了元组,您可以使用mapToPair将元组的RDD转换为具有键和值的PairRDD。

在Java 8中,这可能是

JavaPairRDD<Integer,List<String>> r = 
  rddOfTuples.mapToPair((t)->new Tuple2(
      extractKey(t),
      extractTuples(t)
  ));

请注意,此操作将引入随机播放。

要说明显而易见的,extractKeyextractTuples是要根据需要提取原始元组部分的方法。

由于我对Scala Tuples的了解有限,并且假设输入类似于scala.Tuple5<String,Integer,Integer,Integer,Integer>,这可能是:

JavaPairRDD<Integer,List<String>> r = 
  rddOfTuples.mapToPair((t)->new Tuple2(
      t._1,
      Arrays.asList(t._2,t._3,t._4,t._6)
  ));

但是,如果您事先不知道Tuple的arity(元素数量),那么在scala术语中,它是Product。要动态访问元素,您需要使用Product接口,并选择:

  • int productArity()
  • Object productElement(int n)
  • Iterator<Object> productIterator()

然后它成为常规的Java练习:

JavaPairRDD<Integer,List<String>> r = 
  rddOfTuples.mapToPair((t)->{
    List<String> l = new ArrayList<>(t.productArity()-1);
    for (int i = 1; i < t.productArity(); i++) {
      l.set(i-1,t.productElement(i));
    }
    return new Tuple2<>(t._1,l);
  }));

我希望我没事......上面这段代码是未经测试/未编译的...所以如果你可以让它与更正一起工作,那么随意在这个答案中应用更正...

答案 1 :(得分:1)

您可以尝试使用地图功能,例如在Scala中:

rdd.map { case (k,v1,v2,v3,v4) => (k,(v1,v2,v3,v4)) }

或者也可以使用rdd.groupBy,但这对大型数据集来说可能效率低下。