有以下数据(设定为表t,字段分别为a,b
aa | 11 |
bb | 11 |
cc | 11 |
bb | 11 |
cc | 11 |
cc | 11 |
val k1 = sc.parallelize(List(("aa", 11), ("bb", 11), ("cc", 11), ("bb", 11), ("cc", 11), ("cc", 11)), 2)
val k2= k1.reduceByKey(_+_ )
k2.collect().foreach( println(_))
其实关键的就是reduceByKey(_+_ ) ,真是简洁。
但针对sql :select a, max(b),sum(b) from t group by a 当时想着只要是ByKey的操作应该都是可以实现, 先用 aggregateByKey
val lines = sc.parallelize(List(("aa", 11), ("bb", 11), ("cc", 11), ("bb", 11), ("cc", 11), ("cc", 11)), 2)
val zeroValue = (0, 0)
val seqOp = (u: (Int, Int), v: Int) => { (Math.max(u._1, v), u._2 + v) }
val compOp = (u1: (Int, Int), u2: (Int, Int)) => { (Math.max(u1._1, u2._1), u1._2 + u2._2) }
val vdd3 = lines.aggregateByKey(zeroValue)(seqOp, compOp)
vdd3.collect().foreach(x => println(x._1 + ":" + x._2))
个人理解说明: zeroValue是要先构建好一个类型,这个类型aggregateByKey 函数是最终产生的类型,而seqOp函数中,u是zeroValue的内容,v是lines(RDD)中value的内容,输出的类型也和zeroValue是一致的, compOp是最后把产生的zeroValue类型最后聚合成一个zeroValue类型。
后来想想 reduceByKey肯定是可以实现多个聚合内容的
val k1 = sc.parallelize(List(("aa", 11), ("bb", 11), ("cc", 11), ("bb", 11), ("cc", 11), ("cc", 11)), 2)
val k2= k1.map(x=> (x._1,(x._2,x._2)))
val k3= k2.reduceByKey(
(u1: (Int, Int), u2: (Int, Int)) => { (Math.max(u1._1, u2._1), u1._2 + u2._2) }
)
k3.foreach(x => println(x._1 + ":" + x._2))
由于reduceByKey最终聚合的内容是和RDD中value的内容类型一致的,因为,先构建一个RDD的value内容为(Int,Int) 再利用reduceByKey进行聚合,但不清楚效率上的差异。
看源码可发现ByKey函数基本都是由combineByKey 得到,所以其它函数能做的事情,combineByKey基本也是能做。
val k1 = sc.parallelize(List(("aa", 11), ("bb", 11), ("cc", 11), ("bb", 11), ("cc", 11), ("cc", 11)), 2)
def createCombiner=(v :Int )=>( v,v)
def mergeValue= ( c:(Int,Int), v :Int)=> (Math.max(c._1,v), c._2+v )
def mergeCombiners= (u1: (Int, Int), u2: (Int, Int)) => { (Math.max(u1._1, u2._1), u1._2 + u2._2) }
val k2= k1.combineByKey(createCombiner,
mergeValue,
mergeCombiners
)
k2.foreach(x => println(x._1 + ":" + x._2))
注:由于初学,以上观点可能有误:)
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/134308/viewspace-2090240/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/134308/viewspace-2090240/