自定义累加器类型的功能在1.X版本中就已经提供了,但是使用起来比较麻烦,在2.0版本后,累加器的易用性有了较大的改进,而且官方还提供了一个新的抽象类:AccumulatorV2来提供更加友好的自定义类型累加器的实现方式。实现自定义类型累加器需要继承AccumulatorV2并至少覆写下例中出现的方法,下面这个累加器可以用于在程序运行过程中收集一些文本类信息,最终以Set[String]的形式返回。
class CustomerAccu extends AccumulatorV2[Int, Int] {
//定义一个属性
var sum: Int = 0
//判断是否为空
override def isZero: Boolean = sum == 0
//复制一个累加器
override def copy(): AccumulatorV2[Int, Int] = {
val accu = new CustomerAccu
accu.sum = this.sum
accu
}
//重置累计器
override def reset(): Unit = sum = 0
//累加值,在executor端执行的操作,用户调用
override def add(v: Int): Unit = sum += v
//合并结果,在Driver端进行合并
override def merge(other: AccumulatorV2[Int, Int]): Unit = {
this.sum += other.value
}
//对外暴露方法,得到返回值结果,用户调用
override def value: Int = sum
}
============
测试
object TestCustomerAccu {
def main(args: Array[String]): Unit = {
//1.创建SparkConf
val sparkConf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("TestHBase")
//2.创建SparkContext
val sc = new SparkContext(sparkConf)
//3.定义一个变量
var accu = new CustomerAccu
//注册自定义累加器
sc.register(accu, "sum")
//4.创建一个RDD
val numRDD: RDD[Int] = sc.parallelize(Array(1, 2, 3, 4), 2)
numRDD.map(x => {
accu.add(x)
x
}).collect()
//打印自定义累加器的值
println(accu.value)
sc.stop()
}
}
运行结果: