从apache spark RDD操作(Java)向hashmap添加数据
我使用映射步骤创建了一个JavaRDD对象,其中包含一些我需要的对象。基于这些对象,我想创建一个包含一些统计信息的全局hashmap,但我不知道应该使用哪个RDD操作。起初我认为reduce是解决方案,但后来我发现必须返回相同类型的对象。我对减少项目不感兴趣,而是收集所有机器的所有统计数据(它们可以单独计算,然后相加) 例如:从apache spark RDD操作(Java)向hashmap添加数据,java,apache-spark,mapreduce,rdd,Java,Apache Spark,Mapreduce,Rdd,我使用映射步骤创建了一个JavaRDD对象,其中包含一些我需要的对象。基于这些对象,我想创建一个包含一些统计信息的全局hashmap,但我不知道应该使用哪个RDD操作。起初我认为reduce是解决方案,但后来我发现必须返回相同类型的对象。我对减少项目不感兴趣,而是收集所有机器的所有统计数据(它们可以单独计算,然后相加) 例如: 我有一个RDD对象,其中包含一个整数数组,我想通过将它们放入哈希表来计算每个整数在数组中出现的次数。每台机器都应该计算它自己的哈希表,然后将它们全部放在驱动程序中的一个位
我有一个RDD对象,其中包含一个整数数组,我想通过将它们放入哈希表来计算每个整数在数组中出现的次数。每台机器都应该计算它自己的哈希表,然后将它们全部放在驱动程序中的一个位置。通常,当你想得到一个映射时,你会需要将RDD中的记录转换为键值对,并使用
reduceByKey
您的特定示例听起来与著名的wordcount示例(参见第一个示例)完全相同,只是您希望从对象内的数组中计算整数,而不是从句子(字符串)中计算单词。在Scala中,这将转换为:
import org.apache.spark.rdd.RDD
import scala.collection.Map
class Example {
case class MyObj(ints: Array[Int], otherStuff: String)
def countInts(input: RDD[MyObj]): Map[Int, Int] = {
input
.flatMap(_.ints) // flatMap maps each record into several records - in this case, each int becomes a record
.map(i => (i, 1)) // turn into key-value map, with preliminary value 1 for each key
.reduceByKey(_ + _) // aggregate values by key
.collectAsMap() // collects data into a Map
}
}
通常,您应该让Spark以分布式方式执行尽可能多的操作,并尽可能延迟收集到内存中-如果在减少之前收集值,通常会耗尽内存,除非您的数据集足够小(在这种情况下,您实际上不需要Spark)
编辑:以下是Java中的相同代码(更长,但相同…):
静态类MyObj实现可序列化{
整数[]整数;
串其他东西;
}
映射计数(JavaRDD输入){
返回输入
.flatMap(新的flatMap函数(){
@凌驾
公共Iterable调用(MyObj MyObj)引发异常{
返回array.asList(myObj.ints);
}
})//flatMap将每个记录映射到多个记录中-在本例中,每个int成为一个记录
.mapToPair(新的PairFunction(){
@凌驾
公共Tuple2调用(整数)引发异常{
返回新的Tuple2(整数,1);
}
})//变成键值图,初始值为1
.reduceByKey(新功能2(){
@凌驾
公共整数调用(整数v1、整数v2)引发异常{
返回v1+v2;
}
})//按键聚合值
.collectAsMap();//将数据收集到映射中
}
我最终使用了聚合操作。这正是我想要的。我将提供另一个答案。
static class MyObj implements Serializable {
Integer[] ints;
String otherStuff;
}
Map<Integer, Integer> countInts(JavaRDD<MyObj> input) {
return input
.flatMap(new FlatMapFunction<MyObj, Integer>() {
@Override
public Iterable<Integer> call(MyObj myObj) throws Exception {
return Arrays.asList(myObj.ints);
}
}) // flatMap maps each record into several records - in this case, each int becomes a record
.mapToPair(new PairFunction<Integer, Integer, Integer>() {
@Override
public Tuple2<Integer, Integer> call(Integer integer) throws Exception {
return new Tuple2<>(integer, 1);
}
}) // turn into key-value map, with preliminary value 1
.reduceByKey(new Function2<Integer, Integer, Integer>() {
@Override
public Integer call(Integer v1, Integer v2) throws Exception {
return v1 + v2;
}
}) // aggregate values by key
.collectAsMap(); // collects data into a Map
}