根据购买人数降序,购买人数相同根据价格降序排序

object SparkDemo01 {


  def main(args: Array[String]): Unit = {
    //创建sparkContext
    //    createSparkContextDemo()

    //创建RDD
    //    createRDDDemo()

    //transformation 算子
    //    transformationRddDemo()
    //action 算子
    //    actionRddDemo()


    //简单的 demo
    //    productDemo1()
    //通过 class 实现
    //    productDemo2()
    //通过 case class实现 重点推荐
    //productDemo3()
    //通过隐式转换实现 推荐
    //    productDemo4()
    //使用 ordering 进行排序
    productDemo5()
  }

  def productDemo1(): Unit = {
    val sc = SparkUtils.createSparkContext();
    //手机型号 购买人数 价格
    val rdd = sc.parallelize(List("华为 10 200", "oppo 20 300", "vivo 20 400", "iphone 50 1000"), 1)

    //转换为一个元组结构的 rdd
    val productRdd = rdd.map(products => {
      val product = products.split(" ")
      val name = product(0)
      val person = product(1).toInt
      val price = product(2).toDouble
      (name, person, price)
    })
    //对这个元组的数据进行排序(首先根据购买人数降序,购买人数相同根据价格降序排序)
    productRdd.sortBy(x => (-x._2, -x._3)).printlnInfo()
    sc.stop()
  }

  /**
   * 使用自定义class类进行排序,需要自己实现,序列化,tostring,方法
   */
  def productDemo2(): Unit = {
    val sc = SparkUtils.createSparkContext();
    //手机型号 购买人数 价格
    val rdd = sc.parallelize(List("华为 10 200", "oppo 20 300", "vivo 20 400", "iphone 50 1000"), 1)

    //转换为一个元组结构的 rdd
    val productRdd = rdd.map(products => {
      val product = products.split(" ")
      val name = product(0)
      val person = product(1).toInt
      val price = product(2).toDouble
      new CustomProducts01(name, person, price)
    })
    //对这个元组的数据进行排序(首先根据购买人数降序,购买人数相同根据价格降序排序)
    productRdd.sortBy(x => x).printlnInfo()
    sc.stop()
  }

  /**
   * 使用自定义case class类进行排序,不需要实现序列化,toString ,hashCode,equals,不需要new,这些都是 case class 类默认实现了
   */
  def productDemo3(): Unit = {
    val sc = SparkUtils.createSparkContext();
    //手机型号 购买人数 价格
    val rdd = sc.parallelize(List("华为 10 200", "oppo 20 300", "vivo 20 400", "iphone 50 1000"), 1)

    //转换为一个元组结构的 rdd
    val productRdd = rdd.map(products => {
      val product = products.split(" ")
      val name = product(0)
      val person = product(1).toInt
      val price = product(2).toDouble
      CustomProducts02(name, person, price)
    })
    //对这个元组的数据进行排序(首先根据购买人数降序,购买人数相同根据价格降序排序)
    productRdd.sortBy(x => x).printlnInfo()
    sc.stop()
  }

  //使用自定义class类进行排序,通过隐式转换实现
  def productDemo4(): Unit = {
    val sc = SparkUtils.createSparkContext();
    //手机型号 购买人数 价格
    val rdd = sc.parallelize(List("华为 10 200", "oppo 20 300", "vivo 20 400", "iphone 50 1000"), 1)

    //转换为一个元组结构的 rdd
    val productRdd = rdd.map(products => {
      val product = products.split(" ")
      val name = product(0)
      val person = product(1).toInt
      val price = product(2).toDouble

      new CustomProducts03(name, person, price)
    })

    implicit def productsImplicitly(customProducts03: CustomProducts03): Ordered[CustomProducts03] = (that: CustomProducts03) => {
      //第一次按购买人数排,后一个减去前一个的结果大于 0.代表是降序,返回 1 升序,否则,按价格排,后一个的价格比前一个的价格高,1升序,否则,降序
      if (that.person - customProducts03.person > 0) {
        1
      } else {
        if (that.price - customProducts03.price > 0) 1 else -1
      }
    }

    //对这个元组的数据进行排序(首先根据购买人数降序,购买人数相同根据价格降序排序)
    productRdd.sortBy(x => x).printlnInfo()
    sc.stop()
  }

  /**
   * 使用自定义的 ordering on 进行排序
   */
  def productDemo5(): Unit = {
    val sc = SparkUtils.createSparkContext();
    //手机型号 购买人数 价格
    val rdd = sc.parallelize(List("华为 10 200", "oppo 20 300", "vivo 20 400", "iphone 50 1000"), 1)
    //转换为一个元组结构的 rdd
    val productRdd = rdd.map(products => {
      val product = products.split(" ")
      val name = product(0)
      val person = product(1).toInt
      val price = product(2).toDouble
      (name, person, price)
    })
    /**
     * (Int, Double) 排序字段的类型
     * (String, Int, Double)数据的输入类型
     */
    implicit val sort = Ordering[(Int, Double)].on[(String, Int, Double)](x => (-x._2, -x._3))

    //对这个元组的数据进行排序(首先根据购买人数降序,购买人数相同根据价格降序排序)
    productRdd.sortBy(x => x).printlnInfo()
    sc.stop()
  }

  /**
   * 创建一个自定义的类,用户自定义排序
   * 自定义排序需要实现 ordered 接口,或者Comparable接口 实现序列化接口,输出需要自定义tostring 方法
   *
   * @param name
   * @param person
   * @param price
   */
  class CustomProducts01(val name: String, val person: Int, val price: Double) extends Ordered[CustomProducts01] with Serializable {
    //    override def compareTo(o: CustomProducts): Int = {
    //      if (o.person - this.person > 0) {
    //        1
    //      } else if (o.price - this.price > 0) {
    //        1
    //      } else {
    //        -1
    //      }
    //    }

    //重写比较方法
    override def compare(that: CustomProducts01): Int = {
      //第一次按购买人数排,后一个减去前一个的结果大于 0.代表是降序,返回 1 升序,否则,按价格排,后一个的价格比前一个的价格高,1升序,否则,降序
      if (that.person - this.person > 0) {
        1
      } else {
        if (that.price - this.price > 0) 1 else -1
      }
    }

    override def toString: String = {
      name + " " + person + " " + price
    }
  }


  /**
   * 推荐
   * 使用 case class 实现 自定义排序需要实现 ordered 接口,或者Comparable接口
   *
   * @param name
   * @param person
   * @param price
   */
  case class CustomProducts02(name: String, person: Int, price: Double) extends Ordered[CustomProducts02] {
    //    override def compareTo(o: CustomProducts02): Int = {
    //      if (o.person - this.person > 0) {
    //        1
    //      } else if (o.price - this.price > 0) {
    //        1
    //      } else {
    //        -1
    //      }
    //    }

    //重写比较方法
    override def compare(that: CustomProducts02): Int = {
      //第一次按购买人数排,后一个减去前一个的结果大于 0.代表是降序,返回 1 升序,否则,按价格排,后一个的价格比前一个的价格高,1升序,否则,降序
      if (that.person - this.person > 0) {
        1
      } else {
        if (that.price - this.price > 0) 1 else -1
      }
    }
  }

  class CustomProducts03(val name: String, val person: Int, val price: Double) extends Serializable {
    override def toString: String = {
      name + " " + person + " " + price
    }
  }