当数据集以键值对形式组织的时候,聚合相同的键的元素进行一些统计是很常见操作,如基本RDD上的fold() combine() reduce()等行动操作,pairRDD上则有相应的针对键的转化操作,Spark上有一组类似的操作,可用组合具有相同键的值,这些操作返回RDD 但它们是转化操作而不是行动操作
reduceByKey()与reduce()相当类似,它接收一个函数,并使用函数对值进行合并,reduceByKey()会为数据集中每个键进行并行规约操作,每个规约操作会将键相同的值合并起来,因为数据集可能很大,因此reduceByKey()没有实现向用户程序返回值的行动操作,而是返回一个由各个键和对应键规约出结果值组成的新RDD
——使用Scala中reduceByKey()和mapValue()计算每个键的平均值
rdd.mapvalues(x=>(x,1)).reduceByKey((x,y)=>(x._1+y._1,x._2+y._2))
| key | value |
| panda | 0 |
| pink | 3 |
| pirate | 3 |
| panda | 1 |
| pink | 4 |
执行mapValue
| key | value |
| panda | (0,1) |
| pink | (3,1) |
| pirate | (3,1) |
| panda | (1,1) |
| pink | (4,1) |
执行reduceByKey()进行聚集
| key | value |
| panda | (1,2) |
| pink | (7,2) |
| pirate | (3,1) |
使用MapReduce中的合并器combiner,调用reduceByKey()和foldByKey()会在为每个键计算全局总结果前先自动在每台机器上本地合并
——经典分布式单词计数问题
采用flatmap()来生成以单词为键,以数字1为值得pairRDD 之后采用reduceByKey()对单词进行规约计数
JavaRDD<String> input=sc.textFile("test.txt");
JavaRDD<String> words=input.flatMap(
new FlatMapFunction<String,String>()
{
public Iterable<String> call(String x)
{
return Arrays.asList(x.split(" "));
}
}
);//拆分RDD
JavaPairRDD<String,Integer> result=words.mapToPair
{
new PairFunction<String,String,Integer>()
{
public Tuple2<String,Integer> call(String x)
{
return new Tuple2(x,1);
}
}
}.reduceByKey(
new Function2<Integer,Integer,Integer>()
{
public Integer call(Integer a,Integer b)
{
return a+b;
}
}
);//调用reduce按照key相同进行规约