Spark-udf自定义函数(强类型)

本文详细介绍如何在Spark中自定义聚合函数,通过实例演示了从创建RDD到DS的转换过程,以及如何注册并使用自定义的平均数计算函数。文章深入解析了Aggregator接口的实现,展示了如何进行内部计算、分区合并以及最终结果的输出。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

object learn04 {

  def main(args: Array[String]): Unit = {
    //基本配置
    val conf = new SparkConf().setAppName("learn01").setMaster("local[*]")
    val spark = SparkSession.builder().config(conf).getOrCreate()
    import spark.implicits._
    //创建rdd  -> ds
    val dataRdd = spark.sparkContext.makeRDD(List(1, 2, 3, 4, 5))
    val dataDs= dataRdd.map({
      case (age) => {
        UserBean(age)
      }
    }).toDS()
    //注册函数并显示列名
    val avgFun = new MyAgeAvgClassFunction
    val avgColumn = avgFun.toColumn.name("avgFun")
    dataDs.select(avgColumn).show()
  }

}

case class UserBean(age: BigInt)

case class AvgBuffer(sum: BigInt, count: Int)

/**
  * 求平均数avg
  * 1)继承Aggregator【输入,缓冲,输出】
  * 2)实现方法
  */
class MyAgeAvgClassFunction extends Aggregator[UserBean, AvgBuffer, Double] {

  //初始化缓冲值得大小
  override def zero: AvgBuffer = {
    AvgBuffer(0, 0)
  }

  //内部做计算
  override def reduce(b: AvgBuffer, a: UserBean): AvgBuffer = {
    val c = b.sum + a.age
    val d = b.count + 1
    AvgBuffer(c, d)
  }

  //合并分区时计算
  override def merge(b1: AvgBuffer, b2: AvgBuffer): AvgBuffer = {
    val a = b1.sum + b2.sum
    val b = b1.count + b2.count
    AvgBuffer(a, b)
  }

  //输出
  override def finish(reduction: AvgBuffer): Double = {
    reduction.sum.toDouble / reduction.count
  }

  //用户自定义就用product,其他用scala提供得
  override def bufferEncoder: Encoder[AvgBuffer] = Encoders.product

  override def outputEncoder: Encoder[Double] = Encoders.scalaDouble
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值