spark aggregateByKey算子

aggregateByKey算子的作用是根据key进行聚合操作,代码均是基于java api,先贴代码:

public class AggregateByKeyOperator {

   public static void main(String[] args) {
      SparkConf sparkConf = new SparkConf().setAppName("AggregateOperator")
            .setMaster("local[*]");
      JavaSparkContext sc = new JavaSparkContext(sparkConf);
      List<Tuple2<Integer,Integer>> dataList =  new ArrayList<Tuple2<Integer,Integer>>();
      dataList.add(new Tuple2<Integer, Integer>(1,99));
      dataList.add(new Tuple2<Integer, Integer>(2,78));
      dataList.add(new Tuple2<Integer, Integer>(1,89));
      dataList.add(new Tuple2<Integer, Integer>(2,3));
      dataList.add(new Tuple2<Integer, Integer>(3,3));
      dataList.add(new Tuple2<Integer, Integer>(3,30));
     
      JavaPairRDD<Integer, Integer> dataRdd = sc.parallelizePairs(dataList,1);
      System.out.println("dataRdd.partitions().size():"+dataRdd.partitions().size());
    //用于打印每个分区中的数据
    dataRdd.mapPartitionsWithIndex(new Function2<Integer, Iterator<Tuple2<Integer, Integer>>, Iterator<Tuple2<Integer, Integer>>>() {
         @Override
         public Iterator<Tuple2<Integer, Integer>> call(Integer index, Iterator<Tuple2<Integer, Integer>> t) throws Exception {
            System.out.println("partitionId:"+index);
            while(t.hasNext()) {
               Tuple2 t2 = t.next();
               System.out.println(t2._1+" "+t2._2);
            }
            return t;
         }
      },true).count();
      
      JavaPairRDD<Integer, Integer> aggregateByKey = dataRdd.aggregateByKey(0,new Function2<Integer, Integer, Integer>() {

         private static final long serialVersionUID = 1L;
         @Override
    //seqOp
         public Integer call(Integer t1, Integer t2) throws Exception {
            System.out.println("seq: " + t1 + "\t " + t2);
            return Math.max(t1, t2);
         }
      },new Function2<Integer, Integer, Integer>() {
    //combOp
         private static final long serialVersionUID = 1L;
         @Override
         public Integer call(Integer t1, Integer t2) throws Exception {
            System.out.println("comb: " + t1 + "\t " + t2);
            return t1+t2;
         }
      });

      List<Tuple2<Integer,Integer>> resultRdd = aggregateByKey.collect();
       for (Tuple2<Integer, Integer> tuple2 : resultRdd) {
         System.out.println(tuple2._1+"\t"+tuple2._2);
      }
   }
}

当RDD为一个分区的时候,根据key的不同,可以分为:

key=1: (1,99),(1,89)

key=2: (2,78),(2,3)

key=3:(3,3),(3,30)

这3个组分别进行seqOp,也就是(K,V)里面的V和0进行math.max()运算,运算结果和下一个V继续运算,运算过程是这样的:

key=1:  0,99 =>99,99,89 => 99

key=2:  0,78 => 78,78,3 =>78

key=3: 0,3 =>3,3,30=>30

最终结果是(1,99),(3,30),(2,78)  combOp是把不同分区相同的key的V加起来,由于这里并没有分区,所以实际上是不起作用的,计算结果如下:

(1 99)
(3 30)

(2 78)

如果将代码修改为:

JavaPairRDD<Integer, Integer> dataRdd = sc.parallelizePairs(dataList,2);
即指定2个分区,此时分区0的数据为:

1 99
2 78

1 89

分区1的数据为:

2 3
3 3

3 30

则进行seqOp操作时,只需要每个分区内部进行,

seqOp操作后结果,分区0:(1,99),(2,78)   分区1:(2,3),(3,30),根据上面的分析,combOp操作后的最终结果为:

(1,99),(2,81),(3,30)

同理,将分区数修改为3:,三个分区的数据分别为:

partitionId1 :
1 89
2 3
partitionId0 :
1 99
2 78
partitionId2 :
3 3

3 30

seqOp操作后结果为,分区0:(1,99),(2,78),分区1:(1,89),(2,3),分区2:(3,30),则combOp操作后的最终结果为:

(1,188),(2,81),(3,30)


最后总结一下:

aggregateByKey(p1,p2,p3)算子中,p1,p2,p3三个参数,p1为p2中进行比较的初始值,p2中的逻辑是对每一个分区中的key-value键值对进行操作,在本例中是筛选出每一个分区中key对应的最大的value ,p3的逻辑是对不同分区中p2得到的结果进行累加,若只有一个分区,p3无效。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用Spark算子aggregateByKey举例,可以参考以下代码: ```scala import org.apache.spark.{SparkConf, SparkContext} object Demo { def main(args: Array[String]): Unit = { val conf = new SparkConf().setMaster("local").setAppName("aa") val sc = new SparkContext(conf) // 创建一个包含键值对的列表 val list = List((1,2),(2,7),(1,3),(2,8),(3,9),(3,10),(1,4),(1,5),(2,6),(2,11),(3,12),(3,13)) // 将列表转化为RDD val listRDD = sc.parallelize(list,2) // 使用aggregateByKey算子计算每个键对应的最大值 val result = listRDD.aggregateByKey(0)( (a, b) => math.max(a, b), (x, y) => math.max(x, y) ) // 打印结果 result.collect().foreach(println) } } ``` 以上代码中,我们创建了一个包含键值对的列表,然后将其转化为RDD。接下来,使用aggregateByKey算子计算每个键对应的最大值。在seqOp函数中,我们比较当前值与累加器并返回较大的值。在combOp函数中,我们再次比较两个累加器的值并返回较大的值。最后,通过collect函数将结果打印出来。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [详解Spark核心算子 : aggregateByKey和combineByKey](https://blog.csdn.net/f_n_c_k/article/details/88718262)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值