groupByKey
// 原始数据
val data = sc.parallelize(List(
("zhangsan", 123),
("zhangsan", 321),
("lisi", 96),
("lisi", 75),
("lisi", 23),
("wangwu", 99),
("wangwu", 91),
("wangwu", 92),
("wangwu", 94)
))
列转行
val groupByKey = data.groupByKey
// 结果
// (zhangsan,CompactBuffer(123, 321))
// (wangwu,CompactBuffer(99, 91, 92, 94))
// (lisi,CompactBuffer(96, 75, 23))
行转列
groupByKey.flatMap(e => {
e._2.map((e._1, _))
}).foreach(println)
// 使用flatMapValues
// 这个转换算子 源码可看
groupByKey.flatMapValues(_.iterator).foreach(println)
- mapValues 对每values进行map操作 并与key组成kv
- flatMapValues 对values进行flatMap操作 并与key组成kv
max & min & sum & count
- max spark没有提供封装好的算子,但是提供了
reduceByKeymin同理
// max
val nums = sc.parallelize(1 to 10)
nums
.map((null, _))
.reduceByKey((ov: Int, nv: Int) => {
if (ov >= nv) ov else nv
}).values.foreach(println)
sum也是通过reduceByKey
nums.map((null,_)).reduceByKey(_+_).foreach(println)
count也是
nums.map(_ =>(null,1)).reduceByKey(_+_).values.foreach(println)
avg
简单粗暴的做法
咱们已经会算sum和count了,做除法即可
// 如何算avg?
val sum = nums.map((null,_)).reduceByKey(_+_)
val count = nums.map(_ =>(null,1)).reduceByKey(_+_)
// 得让这俩相遇, 让其进行join
sum.join(count).mapValues(e => e._1/e._2).values.foreach(println)
看看成本
combineByKey
combineByKey传入的三个函数的语义:
- 第一个value进来要怎么处理
- 第二个value进来 这时候和老得value 怎么一块处理(combine)
- 两个combine结果如何 进行 combine
nums.map((null, _)).combineByKey(
(v: Int) => (v, 1),
(ov: (Int, Int), nv: Int) => (ov._1 + nv, ov._2 + 1),
(c1: (Int, Int), c2: (Int, Int)) => (c1._1 + c2._1, c1._2 + c2._2)
)
.mapValues(e => e._1 / e._2)
.values
.foreach(println)
- 这样通过combineByKey 一次性将数据源 算出sum和conunt。并且进行一次shuffle操作就能得出avg