第一种排序方法,比如有数据“name,age,颜值”,我们想按照颜值降序,颜值相同按照年龄升序排。
思路:写个类,将切分出来的数据放入到这个类中,重写这个类的compare方法,用这个类调用sortBy方法。
package com.thy.d20190417
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}
/**
* 实现自定义排序
*/
object CustomSort1 {
def main(args: Array[String]): Unit = {
val conf = new SparkConf().setAppName("IpLocation").setMaster("local[*]")
val sc: SparkContext = new SparkContext(conf)
//排序规则,先按颜值降序,相等再按年龄升序
val users=Array("laoduan 30 99","laozhao 29 9999", "laozhang 28 98", "laoyang 28 99")
//将driver的数据并行化变成 RDD
val lines = sc.parallelize(users)
//切分整理数据,将需要的数据切分出来,放到一个类中,
//这个类继承ordered,然后重写compare,这个类在调用相应的排序方法的时候就会执行重写后的排序规则
val userRDD: RDD[User] = lines.map(line => {
val fields: Array[String] = line.split(" ")
val name: String = fields(0)
val age: Int = fields(1).toInt
val fv: Int = fields(2).toInt
new User(name, age, fv)
})
//u => u表示不传入排序规则,即会调用这个类重写的排序规则
val sorted: RDD[User] = userRDD.sortBy(u => u)
println(sorted.collect().toBuffer)
}
class User(val name:String,val age:Int,val fv:Int)extends Ordered[User] with Serializable {
override def compare(that: User): Int = {
if(this.fv == that.fv){
this.age - that.age // 按照age升序
}else{
-(this.fv - that.fv) // 按照fv降序
}
}
override def toString: String = s"name:$name,age:$age,facavalue:$fv"
}
}
第二种方式:传入一个排序规则,不必将切分后的数据放入到一个类中,然后重写他的compare方法。
package com.thy.d20190417
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}
object CustomSort2 {
def main(args: Array[String]): Unit = {
val conf = new SparkConf().setAppName("IpLocation").setMaster("local[*]")
val sc: SparkContext = new SparkContext(conf)
val users = Array("nanyang 25 99","thy 26 9999", "mingming 28 98", "wazi 22 99")
val lines: RDD[String] = sc.parallelize(users)
val tpRDD: RDD[(String, Int, Int)] = lines.map(line => {
val fields: Array[String] = line.split(" ")
val name: String = fields(0)
val age: Int = fields(1).toInt
val fv: Int = fields(2).toInt
(name, age, fv)
})
// 传入一个排序规则,不改变数据格式,只改变顺序
val sorted: RDD[(String, Int, Int)] = tpRDD.sortBy(tp => new MySort(tp._2,tp._3))
println(sorted.collect().toBuffer)
sc.stop()
}
//排序规则,将age和fv两个排序用到的属性传入,然后进行重写compare方法,当调用sortBy时,new一个本规则传入相应比较属性即可实现排序。
class MySort(val age:Int,val fv:Int)extends Ordered[MySort] with Serializable {
override def compare(that: MySort): Int = {
if(this.fv == that.fv){
this.age - that.age
}else{
-(this.fv - that.fv)
}
}
}
}
第三种方式:使用case class。 case class与class区别:https://mp.youkuaiyun.com/postedit/89355621
package com.thy.d20190417
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}
object CustomSort3 {
def main(args: Array[String]): Unit = {
/**
此段代码同上 tpRDD为:(name,age,fv)
*/
val sorted: RDD[(String, Int, Int)] = tpRDD.sortBy(tp => MySort(tp._2,tp._3))
println(sorted.collect().toBuffer)
}
//case class 默认实现了序列化,不用在 with seria...
case class MySort(age:Int,fv:Int) extends Ordered[MySort]{
override def compare(that: MySort): Int = {
if(this.fv == that.fv){
this.age - that.age
}else{
-(this.fv - that.fv)
}
}
}
}
第四种方式:单独写个SortRules.scala,继承ordering,重写比较规则。排序时import SortRules.类,
package com.thy.d20190417
import com.thy.d20190417.CustomSort4.MySort2
object SortRules {
implicit object OrderingMySort extends Ordering[MySort2]{
override def compare(x: MySort2, y: MySort2): Int = {
if(x.fv == y.fv){
x.age - y.age
}else{
-(x.fv - y.fv)
}
}
}
}
//---------------------------------------------------------------------------------------
package com.thy.d20190417
import org.apache.spark.{SparkConf, SparkContext}
import org.apache.spark.rdd.RDD
object CustomSort4 {
def main(args: Array[String]): Unit = {
/**
此段代码同上 tpRDD为:(name,age,fv)
*/
import SortRules.OrderingMySort
val sorted: RDD[(String, Int, Int)] = tpRDD.sortBy(tp => MySort2(tp._2,tp._3))
println(sorted.collect().toBuffer)
sc.stop()
}
case class MySort2(age:Int, fv: Int)
}
第五种方式:仅需要排序时,利用元组的排序特性即可
//先降序比较fv,在升序比较age
val sorted: RDD[(String, Int, Int)] = tpRDD.sortBy(tp => (-tp._3,tp._2))
/**
其他代码同上
*/
第六种:充分利用元组排序
//充分利用元组的比较规则,元组的比较规则:先比第一,相等再比第二个
//比较前的数据格式
//on[(String,Int,Int)]
//最终比较的数据格式
//Ordering[(Int,Int)]
implicit val rules: Ordering[(String, Int, Int)] = Ordering[(Int,Int)].on[(String,Int,Int)](t => (-t._3,t._2))
val sorted: RDD[(String, Int, Int)] = tpRDD.sortBy(tp =>tp)