排序的方式可以分为6中:
(1)使用一个自定义一个普通的类继承Ordered[User] with Serializable
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("CustomerSort1").setMaster("local[2]")
val sc = new SparkContext(conf)
//定义一个数组类型的值
val user = Array("laoduan 30 99", "laozhao 29 9999", "laozhang 28 98", "laoyang 28 99")
//转换成RDD的类型
val lines = sc.parallelize(user)
//将整个字符串切分为元组的形式
val sorted: RDD[User] = lines.map(x => {
val line = x.split(" ")
val name = line(0)
val age = line(1).toInt
val face = line(2).toInt
new User(name, age, face)
})
//实现自定义排序需要调用sortBy才可以自动调用自定义排序
val r = sorted.sortBy(u=>u)
println(r.collect().toBuffer)
}
class User(val name:String,val age:Int,val face:Int)extends Ordered[User] with Serializable{
override def compare(that: User): Int = {
if (this.face == that.face){
this.age-that.age
}else{
- (this.face-that.face)
}
}
override def toString: String = s"name :$name,age: $age,face:$face"
}
}
(2)和上面的差不多只是new 的位置是不太一样的
import org.apache.spark.{SparkConf, SparkContext}
object CustomSort2 {
//排序规则:首先按照颜值的降序,如果颜值相等,再按照年龄的升序
def main(args: Array[String]): Unit = {
val conf = new SparkConf().setAppName("CustomSort2").setMaster("local[2]")
val sc = new SparkContext(conf)
val user = Array("laoduan 30 99", "laozhao 29 9999", "laozhang 28 98", "laoyang 28 99")
val lines = sc.parallelize(user)
val tpRdd=lines.map(x=>{
val line = x.split(" ")
val name = line(0)
val age = line(1).toInt
val face = line(2).toInt
(name, age, face)
})
val sorted = tpRdd.sortBy(x=>new User1(x._2,x._3))
sorted.foreach(println)
}
//这里定义的参数必须添加类型,传的参数只是自己需要比较的参数,没有重写toString()方法
class User1(val age:Int,val face:Int)extends Ordered[User1] with Serializable {
override def compare(that: User1): Int = {
if (this.face == that.face){
this.age-that.age
}else{
- (this.face-that.face)
}
}
}
}
(3)使用了样例类的方式此时可以不用实现序列化,并且输出不能使用foreach,和并行度有关
import org.apache.spark.{SparkConf, SparkContext}
object CustomSort3 {
//排序规则:首先按照颜值的降序,如果颜值相等,再按照年龄的升序
def main(args: Array[String]): Unit = {
val conf = new SparkConf().setAppName("CustomSort3").setMaster("local[2]")
val sc = new SparkContext(conf)
val user = Array("laoduan 30 99", "laozhao 29 9999", "laozhang 28 98", "laoyang 28 99")
val lines = sc.parallelize(user)
val tpRdd=lines.map(x=>{
val line = x.split(" ")
val name = line(0)
val age = line(1).toInt
val face = line(2).toInt
(name, age, face)
})
val sorted = tpRdd.sortBy(x=> Man(x._2,x._3))
// sorted.foreach(println)
// sc.stop()
//不能使用foreach
println(sorted.collect().toBuffer)
}
//这里定义的参数必须添加类型,传的参数只是自己需要比较的参数,没有重写toString()方法
case class Man(age:Int,face:Int)extends Ordered[Man] {
override def compare(that: Man): Int = {
if (this.face == that.face){
this.age-that.age
}else{
- (this.face-that.face)
}
}
}
}
(4)利用隐式转换的方式
利用隐式转换时,类可以不实现Ordered的特质,普通的类或者普通的样例类即可。
隐式转换支持,隐式方法,隐式函数,隐式的object和隐式的变量,
如果都同时存在,优先使用隐式的object,隐式方法和隐式函数中,会优先使用隐式函数。
隐式转换可以写在任意地方(当前对象中,外部的类中,外部的对象中),如果写在外部,需要导入到当前的对象中即可。
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}
/**
* 利用隐式转换时,类可以不实现Ordered的特质,普通的类或者普通的样例类即可。
隐式转换支持,隐式方法, 隐式函数, 隐式的object 和隐式的变量,
如果都同时存在,优先使用隐式的object,隐式方法和隐式函数中,会优先使用隐式函数。
隐式转换可以写在任意地方(当前对象中,外部的类中,外部的对象中),如果写在外部,需要导入到当前的对象中即可。
*/
object CustomSort4 {
def main(args: Array[String]): Unit = {
val conf = new SparkConf().setAppName("CustomSort4").setMaster("local[*]")
val sc = new SparkContext(conf)
//排序规则:首先按照颜值的降序,如果颜值相等,再按照年龄的升序
val users= Array("laoduan 30 99", "laozhao 29 9999", "laozhang 28 98", "laoyang 28 99")
//将Driver端的数据并行化变成RDD
val lines: RDD[String] = sc.parallelize(users)
//切分整理数据
val tpRDD: RDD[(String, Int, Int)] = lines.map(line => {
val fields = line.split(" ")
val name = fields(0)
val age = fields(1).toInt
val fv = fields(2).toInt
(name, age, fv)
})
//隐式的object方式
implicit object OrderingXiaoRou extends Ordering[XianRou]{
override def compare(x: XianRou, y: XianRou): Int = {
if(x.fv == y.fv) {
x.age - y.age
} else {
y.fv - x.fv
}
}
}
// 如果类没有继承 Ordered 特质
// 可以利用隐式转换 隐式方法 隐式函数 隐式值 隐式object都可以 implicit ord: Ordering[K]
implicit def ordMethod(p: XianRou): Ordered[XianRou] = new Ordered[XianRou] {
override def compare(that: XianRou): Int = {
if (p.fv == that.fv) {
-(p.age - that.age)
} else {
that.fv - p.fv
}
}
}
//利用隐式的函数方式
implicit val ordFunc = (p: XianRou) => new Ordered[XianRou] {
override def compare(that: XianRou): Int = {
if (p.fv == that.fv) {
-(p.age - that.age)
} else {
that.fv - p.fv
}
}
}
//排序(传入了一个排序规则,不会改变数据的格式,只会改变顺序)
val sorted: RDD[(String, Int, Int)] = tpRDD.sortBy(tp => XianRou(tp._2, tp._3))
println(sorted.collect().toBuffer)
sc.stop()
}
}
case class XianRou(age: Int, fv: Int)
(5)利用Ordering的on方法
无需借助任何的类或者对象
只需要利用Ordering特质的on方法即可。
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}
object CustomSort5 {
def main(args: Array[String]): Unit = {
val conf = new SparkConf()
.setMaster("local")
.setAppName(this.getClass.getSimpleName)
val sc = new SparkContext(conf)
val users= Array("laoduan 30 99", "laozhao 29 9999", "laozhang 28 98", "laoyang 28 99")
//将Driver端的数据并行化变成RDD
val lines: RDD[String] = sc.parallelize(users)
// 获得的数据类型是 元组
val prdd = lines.map(t => {
val strings = t.split(" ")
val name = strings(0)
val age = strings(1).toInt
val fv = strings(2).toInt
(name, age, fv)
})
implicit val obj = Ordering[(Int,Int)].on[(String,Int,Int)](t=>(-t._3,t._2))
val sortedrd: RDD[(String, Int, Int)] = prdd.sortBy(t => t)
sortedrd.foreach(println)
}
}
(6)利用元组封装排序条件
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}
object CustomSort6 {
def main(args: Array[String]): Unit = {
val conf = new SparkConf().setAppName("CustomSort5").setMaster("local[*]")
val sc = new SparkContext(conf)
//排序规则:首先按照颜值的降序,如果颜值相等,再按照年龄的升序
val users= Array("laoduan 30 99", "laozhao 29 9999", "laozhang 28 98", "laoyang 28 99")
//将Driver端的数据并行化变成RDD
val lines: RDD[String] = sc.parallelize(users)
//切分整理数据
val tpRDD: RDD[(String, Int, Int)] = lines.map(line => {
val fields = line.split(" ")
val name = fields(0)
val age = fields(1).toInt
val fv = fields(2).toInt
(name, age, fv)})
//充分利用元组的比较规则,元组的比较规则:先比第一,相等再比第二个
val sorted: RDD[(String, Int, Int)] = tpRDD.sortBy(tp => (-tp._3, tp._2))
println(sorted.collect().toBuffer)
sc.stop()
}
}
每天多努力一点