在spark中,利用rdd的sortBy函数进行排序,我们只能单一对某个元素,然而这并不能解决工作中的实际业务。
定义一个类,继承Ordered
实现Serializable序列化(实体要在网络之间传递)
重写compare方法
示例情景:根据美女的颜值与年龄进行排序,如果颜值相等,年龄小的排在前面
object CustomSort {
def main(args: Array[String]): Unit = {
val conf = new SparkConf().setMaster("local[2]").setAppName("CustomSort")
val sc = new SparkContext(conf)
val rdd1 = sc.parallelize(List(("yuihatan", 90, 28, 1), ("angelababy", 90, 27, 2), ("JuJingYi", 95, 22, 3)))
val rdd2 = rdd1.sortBy(x => Girl(x._2, x._3), false)
println(rdd2.collect.toBuffer)
}
}
case class Girl( faceValue: Int, age: Int) extends Ordered[Girl] with Serializable {
override def compare(that: Girl): Int = {
if (this.faceValue == that.faceValue) {
that.age - this.age
} else {
this.faceValue - that.faceValue
}
}
}
在Spark中存在两种对RDD进行排序的函数,分别是 sortBy和sortByKey函数。sortBy是对标准的RDD进行排序,而sortByKey函数是对PairRDD进行排序,也就是有Key和Value的RDD。
soryBy
def sortBy[K](
f: (T) => K,
ascending: Boolean = true,
numPartitions: Int = this.partitions.size
)
该函数最多可以传三个参数:
第一个参数是一个函数,该函数的也有一个带T泛型的参数,返回类型和RDD中元素的类型是一致的;
第二个参数是ascending,这参数决定排序后RDD中的元素是升序还是降序,默认是true,也就是升序;
第三个参数是numPartitions,该参数决定排序后的RDD的分区个数,默认排序后的分区个数和排序之前的个数相等,即为this.partitions.size。
scala>val rdd = sc.parallelize(List(3,2,90,5,12)
scala> rdd.collect
res0: Array[Int] = Array(3, 1, 90, 3, 5, 12)
scala> rdd.sortBy(x => x).collect
res1: Array[Int] = Array(1, 3, 3, 5, 12, 90)
scala> rdd.sortBy(x => x, false).collect
res3: Array[Int] = Array(90, 12, 5, 3, 3, 1)
soryByKey
sortByKey函数作用于Key-Value形式的RDD,并对Key进行排序
def sortByKey(ascending: Boolean = true, numPartitions: Int = self.partitions.size)
第一个参数是ascending,这参数决定排序后RDD中的元素是升序还是降序,默认是true,也就是升序;
第二个参数是numPartitions,该参数决定排序后的RDD的分区个数,默认排序后的分区个数和排序之前的个数相等,即为this.partitions.size。