pair RDD groupByKey countByKey countByValue aggregateByKey reduceByKey 测试

val d = sc.makeRDD(Array(1,2,3,4,5,1,3,5))
val dd = d.map(x=>(x,1))  //构造pair RDD, dd:RDD[(Int,Int)]

1.groupByKey


val dg = dd.groupByKey()  //dg :RDD[(Int, Iterable[Int])]
val dgc = dg.collectAsMap //dgc:Map[Int, Iterable[Int]]
val dgci = dgc.foreach(println(_))
//output
(2,CompactBuffer(1))
(5,CompactBuffer(1, 1))
(4,CompactBuffer(1))
(1,CompactBuffer(1, 1))
(3,CompactBuffer(1, 1))

2.countByKey


val dk = dd.countByKey()  //dk: Map[Int, Long]
dk.foreach(println(_))
(5,2) //key为5出现了2次
(1,2) //key为1出现了2次
(2,1) //key为2出现了1次
(3,2) //key为3出现了2次

3.countByValue


val dv = dd.countByValue()  // dv: Map[(Int, Int),Long]
dv.foreach(println(_))      
//output
((5,1),2)
((3,1),2)
((4,1),1)
((1,1),2)
((2,1),1)

4.aggregateByKey

spark aggregateByKey

aggregateByKey 该函数和aggregate类似,但操作的RDD是Pair类型的。
aggregateByKey函数对PairRDD中相同Key的值进行聚合操作,在聚合过程中同样使用了一个中立的初始值。和aggregate函数类似,aggregateByKey返回值的类型不需要和RDD中value的类型一致。因为aggregateByKey是对相同Key中的值进行聚合操作,所以aggregateByKey函数最终返回的类型还是Pair RDD,对应的结果是Key和聚合好的值;aggregate函数直接是返回非RDD的结果,这点需要注意。在实现过程中,定义了三个aggregateByKey函数原型,但最终调用的aggregateByKey函数都一致。

var data = sc.parallelize(List((1,3),(1,2),(1, 4),(2,3)))
def seq(a:Int, b:Int) : Int ={
 println("seq: " + a + "\t " + b)
 math.max(a,b)
 }
// seq: (a: Int, b: Int)Int
def comb(a:Int, b:Int) : Int ={
println("comb: " + a + "\t " + b)
a + b
 }
// comb: (a: Int, b: Int)Int
data.aggregateByKey(1)(seq, comb).collect
//output
seq: 1   3
seq: 1   2
seq: 1   4
seq: 1   3
comb: 3  2
comb: 5  4
res62: Array[(Int, Int)] = Array((1,9), (2,3))

如果不另外写函数:
var d = sc.parallelize(List((1,3),(1,2),(1, 4),(2,3)))
d.aggregateByKey(1)(
    (a,b)=>{
            println("seq:"+a+"\t"+b);math.max(a,b)
            }
    ,

    (a,b)=>{
            println("combine:"+a+"\t"+b);
            a+b
            }
    ).collect().foreach(println(_))

//output  
seq: 1   3
seq: 1   2
seq: 1   4
seq: 1   3
comb: 3  2
comb: 5  4
Array[(Int, Int)] = Array((1,9), (2,3))



//Exercise 3
val rdd = sc.parallelize(List(
            (("a"), 1.0),
            (("a"), 3.0),
            (("a"), 2.0)
    ))
val rdda = rdd.aggregateByKey("b")(
         {case (aggr , value) => 
         aggr + String.valueOf(value)}, 
         (aggr1, aggr2) => aggr1 +"c"+ aggr2)
rdda.collect().foreach(println(_))
//output
(a,b1.0cb3.0cb2.0)
(b,b4.0)

2016.01.06更新:
aggregateByKey还是不太懂,以下的例子可以加深理解:
aggregateByKey是先用一个初始值对pariRDD的value进行处理,得到新的value,再进行combine

val rdd = sc.parallelize(List(
    (("a"), 1.0),
    (("a"), 3.0),
    (("a"), 2.0)
  ))
  val rdda = rdd.aggregateByKey("b")(
  {case (aggr , value) =>
    println(aggr + String.valueOf(value))
    aggr + String.valueOf(value)},

  (aggr1, aggr2) =>{
    println(aggr1 +" c "+ aggr2)
    aggr1 +" c "+ aggr2
  }
    )
rdda.collect().foreach(println(_))

//这里的初始值是"b",所以第一个函数中的aggr是b,value是pairRDD中的value
将b与value相加组成新的value,此时的pairRDD为:
RDD[("a","b1.0"),("a","b2.0"),("a","b3.0")]
然后进行第二个combine函数:
根据key,对aggr1和aggr2通过combine函数进行合并:aggr1+" c "+aggr2
所以,先是(b1.0,b2.0)=>b1.0 c b2.0
然后(b1.0 c b2.0,b3.0)=>b1.0 c b2.0 c b3.0
b2.0   
b1.0
b3.0
b1.0 c b3.0
b1.0 c b3.0 c b2.0
(a,b1.0 c b3.0 c b2.0)

5.reduceByKey

    val rdd = sc.parallelize(List(
            (("a"), 1.0),
            (("a"), 3.0),
            (("a"), 2.0),
      (("b"),4.0)
    ))
    val reduceByKey = rdd.reduceByKey((a , b) => a+b)
    //reduceByKey:RDD[(String,Double)]
    reduceByKey.collect().foreach(println(_))

你可能感兴趣的:(scala,spark)