spark中的转换算子(二)

combineByKey和aggregateByKey的应用分析

package com.zyc.spark

import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}

/**
* Created with IntelliJ IDEA.
* Author: zyc2913@163.com
* Date: 2020/9/27 16:41
* Version: 1.0
* Description: combineByKey和aggregateByKey的应用分析
*/
object StudyTransformation1 {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf()
      .setMaster("local[*]")
      .setAppName("demo3")
    val sc = new SparkContext(conf)
    /**
     * 11. reduceByKey
     * 11.1.声明def reduceByKey(func: (V, V) => V): RDD[(K, V)]
     * 11.2.参数  二元函数  第一次拿到两个V进行聚合,下次每次拿到聚合结果和新的V再聚合
     * 11.3.返回值 RDD[(K, V)] 和原RDD类型一致
     * 11.4.作用  对pairRDD按照Key聚合Value
     * 11.5.应用举例  统计日志中每个ip出现的次数
     */
    val rdd:RDD[String] = sc.textFile("C:\\Users\\Administrator\\Desktop\\book\\logs\\access.log-20190923")
    val rdd1:RDD[(String,Int)] = rdd.map(x => (x.split("\\s+")(0), 1))  //切分出ip作为key,value是1
    val rdd2:RDD[(String,Int)] = rdd1.reduceByKey((v1: Int, v2: Int) => v1 + v2) //把value聚合相加
    //rdd2.foreach(println)
    //打印结果如下(只复制了部分)
    //(123.53.38.11,883)
    //(104.42.137.111,1)
    //(49.85.2.243,2)
    //(75.164.224.238,2)
    //(171.67.70.80,1)
    //(39.105.49.192,8)

    /**
     * 12. groupByKey
     * 12.1.声明 def groupByKey(): RDD[(K, Iterable[V])] =
     * 12.2.参数
     * 12.3.返回值  K和原RDD相同,Value是一个原RDD的V泛型的Iterable
     * 12.4.作用 将pairRDD中的数据按照Key进行分组
     * 12.5.应用举例:统计ip,每个ip是key,ip出现的次数作为一个数组的值
     */
    rdd1.groupByKey()
    // .foreach(println)
    //打印结果如下(只复制了部分)
    //(104.42.137.111,CompactBuffer(1))
    //(49.85.2.243,CompactBuffer(1, 1))
    //(171.67.70.80,CompactBuffer(1))
    //(39.105.49.192,CompactBuffer(1, 1, 1, 1, 1, 1, 1, 1))

    /**
     * 13. combineByKey
     * 13.1.声明  def combineByKey[C](
     *            createCombiner: V => C, //创建合并器
     *            mergeValue: (C, V) => C, //合并value
     *            mergeCombiners: (C, C) => C //聚合合并器
     *            ): RDD[(K, C)]
     * 13.2.参数
     * 13.3.返回值  RDD[(K, C)] Key和原RDD相同,V变成了C类型
     * 13.4.作用    对RDD按照Key进行聚合,但是聚合过程中V的类型可以改变
     *  所有的聚合,底层都是使用combineByKey或者aggregateByKey
     *  因为分布式数据集RDD的数据,是保存在不同机器的,需要在每个机器先预聚合,最终再进行全局的聚合
     * 13.5.应用举例:计算ip的平均访问量(总访问量total,ip的个数count)
     */

    val rdd3:RDD[(Int,(String,Int))] = rdd2.map((1,_))
              //rdd3的数据样式如下(key,value):
              //(1,(123.53.38.11,883))
              //(1,(104.42.137.111,1))
              //(1,(49.85.2.243,2))
              //(1,(75.164.224.238,2))
    /*
    val rdd4:RDD[(Int,(Int,Int))] = rdd3.combineByKey(
      (v: (String, Int)) => (v._2, 1),
              //通过第一个参数的得到的结果如下(key,value):
              //(883,1)
              //(1,1)
              //(2,1)
              //(2,1)
      (c: (Int, Int), v: (String, Int)) => (c._1 + v._2, c._2 + 1),
              // 每个分区内的聚合(key合并,值相加),结果如下
              // ( (883,1) (123.53.38.11,883) ) =>  (883,2)
              //( (1,1) (104.42.137.111,1) )   =>  (1,2)
              //(  (2,1)  (49.85.2.243,2) )   => (2,3)
              //((2,1) (75.164.224.238,2) )  =>  (2,3)
      (c1: (Int, Int), c2: (Int, Int)) => (c1._1 + c2._1, c1._2 + c2._2)
              //将两个上面的结果合并(key合并,值相加)结果是聚合后的(key,(key,value))
    )
    rdd4.map(x => x._2._1 * 1.0 / x._2._2)  //*1.0表示转换成double型
      .foreach(println)  //打印结果:149.5

     */
     */

    /**
     * 14. aggregateByKey
     * 14.1.声明  def aggregateByKey
     *            (zeroValue: U)
     *            (seqOp: (U, V) => U,
     *            combOp: (U, U) => U
     *            ): RDD[(K, U)] =
     * 14.2.参数  第一个参数列表,类似combineByKey中的第一个函数,但是aggregateByKey的合并器,不需要使用原RDD中的Value,可以直接声明
     *           第二个参数列表,类似combineByKey中的第二第三个函数,作用相同
     * 14.3.返回值  RDD[(K, U)] 和原RDD相同K,v变成U泛型
     * 14.4.作用   分布式的聚合,类似combineByKey
     */
    rdd3.aggregateByKey((0,0))(
      (c:(Int,Int),v:(String,Int)) => (c._1+v._2,c._2+1),
      (c1:(Int,Int),c2:(Int,Int)) => (c1._1+c2._1,c1._2+c2._2)
      )
      .foreach(println)

    /**
     * 15. foldByKey  和aggregateByKey的关系,就像reduceByKey和combineByKey的关系
     *  当 aggregateByKey聚合的后两步函数,完全相同时,可以简化写成foldByKey
     *
     * 15.1.声明def foldByKey(zeroValue: V)(func: (V, V) => V): RDD[(K, V)] =
     * 15.2.参数  两个参数列表,
     * 15.3.返回值
     * 15.4.作用
     *
     */

    /**
     * reduceByKey是combineByKey的简化形式
     *
     * foldByKey是aggregateByKey的简化形式
     */
  }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值