仅提取Java Spark中的某些列

时间:2016-04-27 18:31:28

标签: java apache-spark

我有一个包含10列的文件。提取前3列或特定列的最优雅方法是什么?

例如,这就是我的文件的样子:

john,smith,84,male,kansas
john,doe,48,male,california
tim,jones,22,male,delaware

我想提取到这个:

[john, smith, kansas]
[john, doe, california]
[tim, jones, delaware]

我拥有的是这个,但它没有专门选择我想要的列:

JavaRDD<String> peopleRDD = sc.textFile(DATA_FILE);
peopleRDD.cache().map(lines -> Arrays.asList(lines.split(",")))
                 .forEach(person -> LOG.info(person));

我阅读了following two Stackoverflow帖子,但我仍然无法决定如何执行此操作。

修改 我最终做了以下事情:

JavaRDD<String> peopleRDD = sc.textFile(DATA_FILE);
    peopleRDD.cache().map(lines -> Arrays.asList(new String[]{lines.split(",")[0], 
                                                        lines.split(",")[1], 
                                                        lines.split(",")[3]}
                     .forEach(person -> LOG.info(person));

不是最优雅的解决方案,但如果您有更好的方法,请在此处发布。感谢。

1 个答案:

答案 0 :(得分:1)

编辑:抱歉,我刚刚意识到你要求使用Java解决方案,但我使用过Scala。只有我的第三个建议在Java中有一个等价物(在答案的底部添加)...但是Scala中的Spark确实更好: - )

一种方法是执行split,然后对结果进行模式匹配,以选择所需的列:

peopleRDD.cache().map(_.split(",") match { case Array(a,b,_,_,e) => List(a,b,e) }) 

另一个(取决于您想要的元素组合)是使用takedrop,使用val来避免重复分割。

peopleRDD.cache().map{ line => 
    val parts = line.split(",") 
    parts.take(2) ++ parts.drop(4)
}

(如果您想为RDD中的每个结果元素toList而不是split,则可以在List之后添加Array

实际上,可以使用相同的方法来简化原始解决方案,例如:

peopleRDD.cache().map{ line => 
  val parts = line.split(",")
  List(parts[0], parts[1], parts[4])
}

在Java8中,你可以做同等的,这是一个小小的改进,因为我们避免反复调用split - 如:

peopleRDD.cache().map( line -> {
  Array<String> parts = line.split(",");
  Arrays.asList(new String[]{parts[0], parts[1], parts[4]});
})