源码
def sortBy[K](
f: (T) => K,
ascending: Boolean = true,
numPartitions: Int = this.partitions.length)
(implicit ord: Ordering[K], ctag: ClassTag[K]): RDD[T] = withScope {
this.keyBy[K](f)
.sortByKey(ascending, numPartitions)
.values
}
第一个参数是一个函数,该函数的也有一个带T泛型的参数,返回类型和RDD中元素的类型是一致的;
第二个参数是ascending,从字面的意思大家应该可以猜到,是的,这参数决定排序后RDD中的元素是升序还是降序,默认是true,也就是升序;
第三个参数是numPartitions,该参数决定排序后的RDD的分区个数,默认排序后的分区个数和排序之前的个数相等,即为this.partitions.size。
从sortBy函数的实现可以看出,第一个参数是必须传入的,而后面的两个参数可以不传入。
而且sortBy函数函数的实现依赖于keyBy和sortByKey函数,后面会进行说明
示例
val list: RDD[String] = sc.parallelize(List("taoge,38,99.99", "hangge,32,99.99", "xingge,18,9999.99"))
val tfboys: RDD[Boy] = list.map(f => {
val fields: Array[String] = f.split(",")
val name: String = fields(0)
val age: Int = fields(1).toInt
val fv: Double = fields(2).toDouble
Boy(name, age, fv)
})
//先按照fv 降序排序, 相同后按照年龄升序排序
val sorted1: RDD[Boy] = tfboys.sortBy(f => (-f.fv, f.age)) //借助tuple实现排序规则,注意分区数
sorted1.foreach(f => {
println(f.toString)
})
sc.stop()
}
}
case class Boy(name:String,age:Int,fv:Double)
sortBy底层实现(keyBy+sortByKey)
//sortBy内部实现方式
val keybyed: RDD[((Double, Int), Boy)] = tfboys.keyBy(t => (-t.fv, t.age))
val sorted2: RDD[Boy] = keybyed.sortByKey().values
sorted2.foreach(f => {
println(f.toString)
})
sortBy + 隐式参数实现自定义排序[方式1]
//先按照fv 降序排序, 相同后按照年龄升序排序
implicit val order: Ordering[Boy1] = new Ordering[Boy1] {
override def compare(x: Boy1, y: Boy1): Int = {
if (x.fv == y.fv) {
x.age - y.age
} else {
java.lang.Double.compare(y.fv, x.fv)
}
}
}
tfboys.sortBy(f=>f).foreach(f=>{
println(f.toString)})
sortBy + 隐式参数实现自定义排序[方式2]
//先按照fv 降序排序, 相同后按照年龄升序排序
//借助元祖,元祖规则先比较第一个在比较第二个
implicit val order: Ordering[Boy1] = Ordering[(Double,Int)].on[Boy1](b=>(-b.fv,b.age))
tfboys.sortBy(f=>f).foreach(f=>{
println(f.toString)})
自定义排序+sortBy
//先按照fv 降序排序, 相同后按照年龄升序排序
tfboys.sortBy(f=>f).foreach(f=>{
println(f.toString)})
}
}
//todo 实现Oredered接口,实现compare方法,而不是java的Comparable接口 Comparable的compareTo方法底层调用的还是compare方法
// 先按照fv 降序排序, 相同后按照年龄升序排序
case class Boy(name:String,age:Int,fv:Double) extends Ordered[Boy] {
/**
* x < 0 when this < that
x == 0 when this == that
x > 0 when this > that
*/
override def compare(that: Boy): Int = {
if (this.fv==that.fv){
this.age - that.age
}else{
java.lang.Double.compare(that.fv , this.fv)
}
}