SPARK中实现用户自定义排序

大家:

   好!在spark中对数据进行排序,是在实际工作中是经常用到的,本文是通过样例类的形式在实现用户自定义排序。

准备样例数据,这是第一步,我习惯将数据放在一个文件中。测试文件目录为,C:\test\sort.txt, 样例数据以下所示:

apple	5	5288
sansung	5	5888
huawei	1	3788
mi	4	3799
sony	3	3799
lg	4	2499

说明: 1 数据之间按照TAB键进行隔开  2 样例数据共三列(商品名称,权重,价格)

先用spark的常规的sort的排序,代码如下所示:

package day04

import org.apache.spark.{SparkConf, SparkContext}

/**
  * Created by Administrator on 2017/9/24.
  * 功能: 演示用户自定义排序  自己写的两个sortBy 是不行的
  *
  */
object UserDefinedSort1 {
  def main(args: Array[String]): Unit = {
    val conf=new SparkConf().setAppName("UserDefinedSort1").setMaster("local[2]")
    val sc=new SparkContext(conf)
    val lines=sc.textFile("c://test//sort.txt")
    val rdd=lines.map(line=>{
      val f=line.split("\t")
      (f(0),f(1),f(2))
    })
    //    println(rdd.collect().toBuffer)
//       val sort=rdd.sortBy(_._2,true).sortBy(_._3,false)
    val sort=rdd.sortBy(_._2,true)
    val sort1=sort.sortBy(_._3,true)
    println(sort1.collect().toBuffer)
    sc.stop()


  }
}

为了验证实验的效果,我做了以下的尝试,在此仅仅截取核心的代码和结果进行展示

val sort=rdd.sortBy(_._2,true)
println(sort.collect().toBuffer)

--true 结果  说明单个字段是按照从小到大的,其余字段没有参与排序
ArrayBuffer((huawei,1,3788), (sony,3,3799), (mi,4,3799), (lg,4,2499), (apple,5,5288), (sansung,5,5888))

val sort=rdd.sortBy(_._2,false)
println(sort.collect().toBuffer)

--false 结果 说明单个字段是按照从大到小的,其余字段没有参与排序 
ArrayBuffer((apple,5,5288), (sansung,5,5888), (mi,4,3799), (lg,4,2499), (sony,3,3799), (huawei,1,3788))
	
	
val sort=rdd.sortBy(_._2,false)
val sort1=sort.sortBy(_._3,false)
println(sort1.collect().toBuffer)

---先按照等级降序,再按照价格降序。 可以看到,没有按照预期的效果进行展现,似乎只有价格降序起了作用
ArrayBuffer((sansung,5,5888), (apple,5,5288), (mi,4,3799), (sony,3,3799), (huawei,1,3788), (lg,4,2499))


val sort=rdd.sortBy(_._2,true)
val sort1=sort.sortBy(_._3,false)
println(sort1.collect().toBuffer)

--先按照等级升序,在同一个等级内按照价格降序,可以看到,没有按照预期的效果进行展现,似乎只有价格降序起了作用
ArrayBuffer((sansung,5,5888), (apple,5,5288), (sony,3,3799), (mi,4,3799), (huawei,1,3788), (lg,4,2499))

val sort=rdd.sortBy(_._2,false)
val sort1=sort.sortBy(_._3,true)
println(sort1.collect().toBuffer)

---先按照等级降序,再按照价格升序, 可以看到,没有按照预期的效果进行展现,似乎只有价格升序起了作用
ArrayBuffer((lg,4,2499), (huawei,1,3788), (mi,4,3799), (sony,3,3799), (apple,5,5288), (sansung,5,5888))


val sort=rdd.sortBy(_._2,true)
val sort1=sort.sortBy(_._3,true)
println(sort1.collect().toBuffer)
	
---先按照等级升序,再按照价格升序,	可以看到,没有按照预期的效果进行展现,似乎只有价格升序起了作用
ArrayBuffer((lg,4,2499), (huawei,1,3788), (sony,3,3799), (mi,4,3799), (apple,5,5288), (sansung,5,5888))

可以看到,单个的sort是没有问题的。但是,如果涉及到两个字段的排序,就有问题了,而这往往是实际工作中需要的。

为此,引入了样例类,代码以下所示:

package day04

import org.apache.spark.{SparkConf, SparkContext}

/**
  * Created by Administrator on 2017/9/24.
  * 功能: 演示用户自定义排序  继承Ordered 类,重写compare方法
  *
  */
// 先定义一个样例类
case class Goods(val simi:Int,val price:Int) extends Ordered[Goods] with Serializable
{

  override def compare(that:Goods):Int={
    if(this.price==that.price){
      that.simi-this.simi   //如果价格相等,权重从大到小
    }else{
      this.price-that.price  //价格从小到大排序
    }

  }
}



object UserDefinedSort {
  def main(args: Array[String]): Unit = {
    val conf=new SparkConf().setAppName("UserDefinedSort").setMaster("local[2]")
    val sc=new SparkContext(conf)
    val lines=sc.textFile("c://test//sort.txt")
    val rdd=lines.map(line=>{
      val f=line.split("\t")
      (f(0),f(1).toInt,f(2).toInt)
    })
    val sort=rdd.sortBy(x=>Goods(x._2,x._3),true)

    println(sort.collect().toBuffer)


  }
}

核心点:  先定义一个样例类  实现Ordered 类,重写compare方法 ,以及序列化

程序运行结果以下所示:

ArrayBuffer((lg,4,2499), (huawei,1,3788), (mi,4,3799), (sony,3,3799), (apple,5,5288), (sansung,5,5888))

说明: 1 如果在程序的第35行,排序的时候将true修改为了false,结果为以下的所示:

--false val sort=rdd.sortBy(x=>Goods(x._2,x._3),false)
ArrayBuffer((sansung,5,5888), (apple,5,5288), (sony,3,3799), (mi,4,3799), (huawei,1,3788), (lg,4,2499))

 个人认为,这样的写法相当于又绕了一层,容易混淆。建议把所有的排序规则都写在compare方法内

猜你喜欢

转载自blog.csdn.net/zhaoxiangchong/article/details/78409267