前篇使用过spark实现MapReduce实现对相同字母组成的单词汇总
但是涉及到了groupByKey算子,存在shuffle过程,效率有提高空间,就考虑使用累加器这个分布式共享只写变量数据结构来避免shuffle进而提高效率
代码如下
object WordCollect1 {
def main(args: Array[String]): Unit = {
val sc = new SparkContext(new SparkConf().setMaster("local[*]").setAppName("WordCollect"))
val rdd: RDD[String] = sc.textFile("datas/word2.txt",2)
// new 自定义的累加器
val accumulator = new WordCollectAccumulator()
// 上下文环境注册累加器
sc.register(accumulator,"WordCollectAccumulator")
val value: RDD[String] = rdd.flatMap(
line => {
val strings: Array[String] = line.split(" ")
strings
}
)
value.foreach(word => accumulator.add(word))
println(accumulator.value)
sc.stop()
}
// 这里使用一个帮助类来实现数据的统计放入list集合中,试过使用string来储存数据,但是总是会出现重复数据,目前还未明白问题所在,所以换了种思路解决
case class WordHelp(var list:List[String])
class WordCollectAccumulator extends AccumulatorV2[String,mutable.Map[String, WordHelp]]{
private var wordCollect: mutable.Map[String,WordHelp] = mutable.Map()
// 累加器是否为初始状态
override def isZero: Boolean = wordCollect.isEmpty
// 复制累加器
override def copy(): AccumulatorV2[String, mutable.Map[String, WordHelp]] = {
new WordCollectAccumulator
}
// 重置累加器
override def reset(): Unit = wordCollect.clear()
// 向累加器中添加数据
override def add(v: String): Unit = {
// 转换为小写并转换为字符数组
val array: Array[Char] = v.toLowerCase.toCharArray
// 进行排序来是的key值可以相同
val sorted: Array[Char] = array.sorted
val str: String = sorted.mkString
// 初始化辅助类
val word: WordHelp = wordCollect.getOrElse(str, WordHelp(List()))
// 将数据追加到辅助类的list集合来储存
word.list = word.list:+v
// 注意要更新数据
wordCollect.update(str,word)
}
// 合并累加器
override def merge(other: AccumulatorV2[String, mutable.Map[String, WordHelp]]): Unit = {
val map1: mutable.Map[String, WordHelp] = wordCollect
val map2: mutable.Map[String, WordHelp] = other.value
map2.foreach{
case (k,v) =>{
// 思路和add一样
val word: WordHelp = map1.getOrElse(k, WordHelp(List()))
// 这里时两个链表的组合,注意
word.list = word.list++:v.list
// 更新数据
map1.update(k,word)
}
}
}
// 返回累加器的结果
override def value: mutable.Map[String, WordHelp] = wordCollect
}
}
结果:
在实现的过程中自定义累加器out输出端原想都用string字符串,但是发现统计时总会有重复值出现,目前还未明白问题所在,所以换了种思路解决,添加了一个辅助类封装了一个list集合来对数据存储。