【scala原理系列】sortWith sortBy sorted Ordering 排序用法示例源码分析

【scala原理系列】sortWith sortBy sorted Ordering 用法示例源码分析

一、概述

Ordering是一个特质,其实例代表了一种用于对类型实例进行排序的策略。

Ordering的伴生对象定义了许多隐式对象,用于处理AnyVal的子类型(例如IntDouble)、String和其他类型。

sortWithsortBysorted三个方法的工作原理

  • **sortWith方法:**它使用传入的比较函数对集合进行排序。在排序过程中,根据比较函数的返回值来决定元素的顺序。如果比较函数返回true,则表示第一个参数应该排在第二个参数之前;如果返回false,则表示第一个参数应该排在第二个参数之后。通过多次应用比较函数,将集合中的元素逐步排序。这种方法实现了稳定的排序,即相等的元素在排序后的序列中与原始序列中的顺序相同。

  • sortBy方法:它使用传入的转换函数将集合中的元素映射到另一个域,并根据转换后的值进行排序。在排序过程中,使用隐式的Ordering对象来比较转换后的值。通过比较转换后的值,可以确定元素的顺序。这种方法也实现了稳定的排序,即相等的元素在排序后的序列中与原始序列中的顺序相同。

  • sorted方法:它使用给定的Ordering对象对集合进行排序。Ordering对象定义了元素之间的比较规则。在排序过程中,通过调用Ordering对象的compare方法来比较元素的顺序。这种方法同样实现了稳定的排序,即相等的元素在排序后的序列中与原始序列中的顺序相同。

这三个方法都返回一个新的集合,并不会修改原始集合。它们使用的排序算法是基于数组的快速排序算法(通过java.util.Arrays.sort方法实现)。需要注意的是,sortWithsorted方法可以直接使用比较函数或Ordering对象,而sortBy方法需要传入一个转换函数,并依赖于隐式的Ordering对象来进行排序。

1.内置排序

要根据一个或多个成员变量对实例进行排序,可以利用这些内置的排序方式使用Ordering.byOrdering.on

import scala.util.Sorting
val pairs = Array(("a", 5, 2), ("c", 3, 1), ("b", 1, 3))

// 按第二个元素排序
Sorting.quickSort(pairs)(Ordering.by[(String, Int, Int), Int](_._2))

// 先按第三个元素排序,然后按第一个元素排序
Sorting.quickSort(pairs)(Ordering[(Int, String)].on(x => (x._3, x._1)))

2.指定compare(a: T, b: T)排序

Ordering[T]通过指定compare(a: T, b: T)来实现,该方法决定如何对两个实例ab进行排序。

Ordering[T]的实例可以被像scala.util.Sorting这样的工具用于对Array[T]等集合进行排序。

 import scala.util.Sorting

  case class Person(name: String, age: Int)
  val people = Array(Person("bob", 30), Person("ann", 32), Person("carl", 19))

  // 按年龄排序
  object AgeOrdering extends Ordering[Person] {
    def compare(a: Person, b: Person) = a.age compare b.age
  }
  Sorting.quickSort(people)(AgeOrdering)
  people.foreach(println)
//  Person(carl,19)
//  Person(bob,30)
//  Person(ann,32)

这个特质和scala.math.Ordered提供了相同的功能,但是使用不同的方式实现。类型T可以通过扩展Ordered来给自己赋予一种排序方式。使用Ordering,可以以多种其他方式对同一类型进行排序。

OrderedOrdering都提供了隐式转换,使它们可以互换使用

您可以导入scala.math.Ordering.Implicits以获取其他隐式排序方式

二、用法

1.Ordering特质方法:

  • tryCompare(x: T, y: T): Option[Int]:返回是否定义了xy之间的比较,并返回compare(x, y)的结果。
  • compare(x: T, y: T): Int:返回一个整数,表示xy的比较结果的符号。
  • lteq(x: T, y: T): Boolean:在排序中,如果x <= y,则返回true。
  • gteq(x: T, y: T): Boolean:在排序中,如果x >= y,则返回true。
  • lt(x: T, y: T): Boolean:在排序中,如果x < y,则返回true。
  • gt(x: T, y: T): Boolean:在排序中,如果x > y,则返回true。
  • equiv(x: T, y: T): Boolean:在排序中,如果x == y,则返回true。
  • max(x: T, y: T): T:如果x >= y,则返回x,否则返回y
  • min(x: T, y: T): T:如果x <= y,则返回x,否则返回y
  • reverse: Ordering[T]:返回与此排序相反的排序方式。
  • on[U](f: U => T): Ordering[U]:给定一个从UT的函数f,创建一个Ordering[U],其compare函数等效于Ordering[T].compare(f(x), f(y))
  • Ops(lhs: T):内部类,定义了可用于T的比较操作符。
  • mkOrderingOps(lhs: T): Ops:隐式方法,使用在scala.math.Ordering.Ops中定义的比较操作符来扩展T

LowPriorityOrderingImplicits特质中,还定义了两个额外的隐式方法:

  • ordered[A <% Comparable[A]]: Ordering[A]当没有其他隐式Ordering可用时,将Ordered[A]转换为Ordering[A]。同时也支持Java互操作。
  • comparatorToOrdering[A](implicit cmp: Comparator[A]): Ordering[A]Comparator[A]转换为Ordering[A]

这些方法提供了对类型实例进行排序所需的功能和灵活性。通过实现Ordering的不同策略,可以在多种情况下定制化地对对象进行排序。

2.ordering伴生对象方法

这是scala.math.Ordering特质的伴生对象,包含了许多隐式的Ordering以及构造新Ordering的方法。

  • apply[T](implicit ord: Ordering[T])根据隐式参数获取对应类型的Ordering实例
  • trait ExtraImplicits额外的隐式方法,提供了一些方便的操作。
    • implicit def seqDerivedOrdering[CC[X] <: scala.collection.Seq[X], T](implicit ord: Ordering[T]): Ordering[CC[T]]:针对继承自Seq的集合类型,根据元素类型的Ordering进行比较。
    • implicit def infixOrderingOps[T](x: T)(implicit ord: Ordering[T]): Ordering[T]#Ops:将具有隐式Ordering的类型转换为支持比较操作符的Ops类。
  • object Implicits extends ExtraImplicits:未在默认作用域中的隐式对象。
  • def fromLessThan[T](cmp: (T, T) => Boolean): Ordering[T]根据给定的函数创建一个Ordering实例
  • def by[T, S](f: T => S)(implicit ord: Ordering[S]): Ordering[T]:根据给定的函数隐式Ordering创建一个基于属性的Ordering
  • 定义了一系列隐式Ordering对象,分别对应不同的数据类型(如Unit、Boolean、Byte等)。
  • 针对元组类型定义了一系列的隐式Ordering,支持对元组的比较

这些方法和隐式对象提供了一系列便捷的操作默认的Ordering实例,使得在Scala中进行排序和比较变得更加简单和灵活

3.sortWith sortBy sorted


3.1 sortWith(lt: (A, A) => Boolean)

将此集合根据比较函数进行排序。

  • 排序是稳定的,即相等的元素(根据 lt 判断)在排序后的序列中与原始序列中的顺序相同

参数:

  • lt:比较函数,用于测试其第一个参数是否在所需的顺序中位于第二个参数之前。

返回值:

  • 一个由此集合的元素根据比较函数 lt 排序后组成的集合。

示例:

List("Steve", "Tom", "John", "Bob").sortWith(_.compareTo(_) < 0) // List("Bob", "John", "Steve", "Tom")

3.2 sortBy[B](f: A => B)(implicit ord: Ordering[B])

根据通过将隐式给定的 Ordering 转换函数应用于转换为另一个域 B 的元素来对此集合进行排序。

  • 排序是稳定的,即相等的元素(根据 ord.lt(f(x), f(y)) 判断)在排序后的序列中与原始序列中的顺序相同。

参数:

  • f:将元素映射到其他域 B 的转换函数。
  • ord:假设在域 B 上定义的排序。

返回值:

  • 一个由此集合的元素根据排序 x < y(其中 x < y 如果 ord.lt(f(x), f(y)))的排序组成的集合。

示例:

val words = "The quick brown fox jumped over the lazy dog".split(' ')
words.sortBy(x => (x.length, x.head)) 
// Array("The", "dog", "fox", "the", "lazy", "over", "brown", "quick", "jumped")

3.3 sorted[B >: A](implicit ord: Ordering[B])

根据给定的 Ordering 对象对此集合进行排序。

  • 排序是稳定的,即相等的元素(根据 lt 判断)在排序后的序列中与原始序列中的顺序相同。

参数:

  • ord:被用来比较元素的 Ordering

返回值:

  • 一个由此集合的元素根据排序 ord 组成的集合。

示例:

List("apple", "banana", "cherry", "date").sorted // List("apple", "banana", "cherry", "date")

示例

比较示例

tryCompare lt max

object sortTest1 extends App{
  import scala.math.Ordering

  // 定义一个自定义类
  case class Person(name: String, age: Int)

  // 创建一些 Person 对象
  val john = Person("John", 30)
  val alice = Person("Alice", 25)
  val bob = Person("Bob", 35)

  // 创建一个 Ordering[Person] 实例
  object AgeOrdering extends Ordering[Person] {
    def compare(a: Person, b: Person): Int = a.age.compare(b.age)
  }

  // 使用 tryCompare 方法比较两个 Person 对象的年龄
  val result1 = AgeOrdering.tryCompare(john, alice) // Some(1)
  val result2 = AgeOrdering.tryCompare(alice, bob) // Some(-1)
  val result3 = AgeOrdering.tryCompare(john, john) // Some(0)

  println(result1)
  println(result2)
  println(result3)

  // 使用 lt 方法比较两个 Person 对象的年龄
  val result4 = AgeOrdering.lt(john, alice) // false
  val result5 = AgeOrdering.lt(alice, bob) // true

  println(result4)
  println(result5)

  // 使用 max 和 min 方法获取两个 Person 对象中年龄较大和较小的对象
  val maxAgePerson = AgeOrdering.max(john, alice) // Person("John", 30)
  val minAgePerson = AgeOrdering.min(john, alice) // Person("Alice", 25)

  println(maxAgePerson)
  println(minAgePerson)
}
//Some(1)
//Some(-1)
//Some(0)
//false
//true
//Person(John,30)
//Person(Alice,25)

在这个示例中,我们首先定义了一个Person类,用于排序对象。然后,我们创建了一些Person对象:John、Alice和Bob。接下来,我们定义了一个AgeOrdering对象,实现了Ordering[Person],并重写了compare方法以按照年龄进行比较。然后,我们使用不同的方法进行比较和排序:

  • tryCompare方法返回一个Option[Int],表示是否定义了两个对象之间的比较,并返回compare方法的结果。

  • ltgtlteqgteqequiv方法分别返回布尔值,表示两个对象之间的比较结果。

  • maxmin方法返回两个对象中年龄较大和较小的对象。

Ordering.fromLessThan

object sortTest2 extends App{

  import scala.math.Ordering

  // 定义一个自定义类
  case class Person(name: String, age: Int)

  // 创建一些 Person 对象
  val john = Person("John", 30)
  val alice = Person("Alice", 25)
  val bob = Person("Bob", 35)

  // 使用 Ordering.fromLessThan 方法创建一个基于年龄的 Ordering[Person]
  val ageOrdering = Ordering.fromLessThan[Person]((a, b) => a.age < b.age)

  // 使用 compare 方法比较两个 Person 对象的年龄
  val result1 = ageOrdering.compare(john, alice) // 1
  val result2 = ageOrdering.compare(alice, bob) // -1
  val result3 = ageOrdering.compare(john, john) // 0

  println(result1)
  println(result2)
  println(result3)
}
//1
//-1
//0

排序示例1

自定义排序接口compare

object sortTest0 extends App{
  import scala.util.Sorting

  case class Person(name: String, age: Int)
  val people = Array(Person("bob", 30), Person("ann", 32), Person("carl", 19))

  // 按年龄排序
  object AgeOrdering extends Ordering[Person] {
    def compare(a: Person, b: Person) = a.age compare b.age
  }
  //  Sorting.quickSort(people)(AgeOrdering)
  Sorting.quickSort(people)(AgeOrdering)

  people.foreach(println)
  //  Person(carl,19)
  //  Person(bob,30)
  //  Person(ann,32)
}

Ordering.fromLessThan

import scala.math.Ordering

object Main extends App {
  // 创建一个根据字符串长度比较的排序器
  val lengthOrdering = Ordering.fromLessThan[String](_.length < _.length)

  val words = List("apple", "banana", "cat", "dog")
  val sortedWords = words.sorted(lengthOrdering)
  println(sortedWords)  // 输出:List(cat, dog, apple, banana)
}

Ordering.by(隐)

import scala.math.Ordering

case class Person(name: String, age: Int)

object Main extends App {
  // 根据人员的姓名长度创建一个排序器
  implicit val nameLengthOrdering: Ordering[Person] = Ordering.by(_.name.length)

  val people = List(
    Person("Alice", 25),
    Person("Bob", 30),
    Person("Charlie", 20)
  )

  val sortedPeople = people.sorted
  println(sortedPeople)  // 输出:List(Bob, Alice, Charlie)
}

Ordering.Int(隐式转换)

object impCompTest2 extends App {
  // 使用隐式比较操作符进行比较
  val a = 5
  val b = 10
  val ordering = Ordering.Int
  val lessThan = ordering.lt(a, b)
  val greaterThanEqual = ordering.gteq(a, b)
  println(lessThan)  // 输出:true
  println(greaterThanEqual)  // 输出:false
}
//true
//false

sorted sortBy sortWith

object sortTest4 extends App{
  // 创建一个包含一些整数的列表
  val nums = List(5, 3, 8, 1, 6)

  // 使用sortWith方法根据数字的大小进行排序
  val sortedNums1 = nums.sortWith(_ < _) // List(1, 3, 5, 6, 8)
  val sortedNums2 = nums.sortWith(_ > _) // List(8, 6, 5, 3, 1)

  println(sortedNums1)
  println(sortedNums2)

  // 使用sortBy方法根据数字的绝对值进行排序
  val sortedNums3 = nums.sortBy(Math.abs) // List(1, 3, 5, 6, 8)

  println(sortedNums3)

  // 创建一个包含一些字符串的列表
  val words = List("apple", "banana", "cherry", "date")

  // 使用sorted方法根据字符串的长度进行排序
  val sortedWords1 = words.sorted // List("apple", "banana", "cherry", "date")
  val sortedWords2 = words.sorted(Ordering[String].reverse) // List("date", "cherry", "banana", "apple")

  println(sortedWords1)
  println(sortedWords2)
}
//List(1, 3, 5, 6, 8)
//List(8, 6, 5, 3, 1)
//List(1, 3, 5, 6, 8)
//List(apple, banana, cherry, date)
//List(date, cherry, banana, apple)

源码

ordering

/**
 * Ordering是一个特质,其实例代表了一种用于对类型实例进行排序的策略。
 *
 * Ordering的伴生对象定义了许多隐式对象,用于处理AnyVal的子类型(例如Int、Double)、String和其他类型。
 *
 * 要根据一个或多个成员变量对实例进行排序,可以利用这些内置的排序方式使用Ordering.by和Ordering.on:
 *
 * ```
 * import scala.util.Sorting
 * val pairs = Array(("a", 5, 2), ("c", 3, 1), ("b", 1, 3))
 *
 * // 按第二个元素排序
 * Sorting.quickSort(pairs)(Ordering.by[(String, Int, Int), Int](_._2))
 *
 * // 先按第三个元素排序,然后按第一个元素排序
 * Sorting.quickSort(pairs)(Ordering[(Int, String)].on(x => (x._3, x._1)))
 * ```
 *
 * Ordering[T]通过指定compare(a:T, b:T)来实现,该方法决定如何对两个实例a和b进行排序。Ordering[T]的实例可以被像scala.util.Sorting这样的工具用于对Array[T]等集合进行排序。
 *
 * 例如:
 *
 * ```
 * import scala.util.Sorting
 *
 * case class Person(name:String, age:Int)
 * val people = Array(Person("bob", 30), Person("ann", 32), Person("carl", 19))
 *
 * // 按年龄排序
 * object AgeOrdering extends Ordering[Person] {
 *   def compare(a:Person, b:Person) = a.age compare b.age
 * }
 * Sorting.quickSort(people)(AgeOrdering)
 * ```
 *
 * 这个特质和scala.math.Ordered提供了相同的功能,但是使用不同的方式实现。类型T可以通过扩展Ordered来给自己赋予一种排序方式。使用Ordering,可以以多种其他方式对同一类型进行排序。Ordered和Ordering都提供了隐式转换,使它们可以互换使用。
 *
 * 您可以导入scala.math.Ordering.Implicits以获取其他隐式排序方式。
 *
 * @author Geoffrey Washburn
 * @version 0.9.5, 2008-04-15
 * @since 2.7
 * @see [[scala.math.Ordered]], [[scala.util.Sorting]]
 */
@annotation.implicitNotFound(msg = "没有为${T}定义隐式的Ordering。")
trait Ordering[T] extends Comparator[T] with PartialOrdering[T] with Serializable {
  outer =>

  /** 返回是否定义了`x`和`y`之间的比较,并返回`compare(x, y)`的结果。 */
  def tryCompare(x: T, y: T) = Some(compare(x, y))

 /** 返回一个整数,表示x与y的比较结果的符号。
   *
   * 结果符号的含义如下:
   *
   *  - 如果 x < y,则为负数
   *  - 如果 x > y,则为正数
   *  - 否则为零(如果 x == y)
   */
  def compare(x: T, y: T): Int

  /** 在排序中,如果`x` <= `y`,则返回true。 */
  override def lteq(x: T, y: T): Boolean = compare(x, y) <= 0

  /** 在排序中,如果`x` >= `y`,则返回true。 */
  override def gteq(x: T, y: T): Boolean = compare(x, y) >= 0

  /** 在排序中,如果`x` < `y`,则返回true。 */
  override def lt(x: T, y: T): Boolean = compare(x, y) < 0

  /** 在排序中,如果`x` > `y`,则返回true。 */
  override def gt(x: T, y: T): Boolean = compare(x, y) > 0

  /** 在排序中,如果`x` == `y`,则返回true。 */
  override def equiv(x: T, y: T): Boolean = compare(x, y) == 0

  /** 如果`x` >= `y`,则返回`x`,否则返回`y`。 */
  def max(x: T, y: T): T = if (gteq(x, y)) x else y

  /** 如果`x` <= `y`,则返回`x`,否则返回`y`。 */
  def min(x: T, y: T): T = if (lteq(x, y)) x else y

  /** 返回与此排序相反的排序方式。 */
  override def reverse: Ordering[T] = new Ordering[T] {
    override def reverse = outer
    def compare(x: T, y: T) = outer.compare(y, x)
  }

  /** 给定一个从U到T的函数f,创建一个Ordering[U],其compare函数等效于:
    *
    * ```
    * def compare(x:U, y:U) = Ordering[T].compare(f(x), f(y))
    * ```
    */
  def on[U](f: U => T): Ordering[U] = new Ordering[U] {
    def compare(x: U, y: U) = outer.compare(f(x), f(y))
  }

  /** 这个内部类定义了可用于`T`的比较操作符。 */
  class Ops(lhs: T) {
    def <(rhs: T) = lt(lhs, rhs)
    def <=(rhs: T) = lteq(lhs, rhs)
    def >(rhs: T) = gt(lhs, rhs)
    def >=(rhs: T) = gteq(lhs, rhs)
    def equiv(rhs: T) = Ordering.this.equiv(lhs, rhs)
    def max(rhs: T): T = Ordering.this.max(lhs, rhs)
    def min(rhs: T): T = Ordering.this.min(lhs, rhs)
  }

  /** 这个隐式方法使用在`scala.math.Ordering.Ops`中定义的比较操作符来扩展`T`。 */
  implicit def mkOrderingOps(lhs: T): Ops = new Ops(lhs)
}

trait LowPriorityOrderingImplicits {
  /** 这将与所有可用的优雅隐式Orderings冲突,但由于优先级隐式通过子类化进行魔法实现,
   * 只有在没有其他方法适用时,`Ordered[A] => Ordering[A]` 才会出现。由于 `Ordered[A]` 已经扩展了 `Comparable[A]`,我们也可以进行一些Java互操作。
   */
  implicit def ordered[A <% Comparable[A]]: Ordering[A] = new Ordering[A] {
    def compare(x: A, y: A): Int = x compareTo y
  }
  implicit def comparatorToOrdering[A](implicit cmp: Comparator[A]): Ordering[A] = new Ordering[A] {
    def compare(x: A, y: A) = cmp.compare(x, y)
  }
}
 
/**
 * 这是[[scala.math.Ordering]]特质的伴生对象。
 *
 * 它包含许多隐式排序以及构建新排序的方法。
 */
object Ordering extends LowPriorityOrderingImplicits {
  def apply[T](implicit ord: Ordering[T]) = ord

  trait ExtraImplicits {
    /**
     * 不在标准范围内,由于潜在的发散性:
     * 例如 `implicitly[Ordering[Any]]` 在其存在时会导致发散。
     */
    implicit def seqDerivedOrdering[CC[X] <: scala.collection.Seq[X], T](implicit ord: Ordering[T]): Ordering[CC[T]] =
      new Ordering[CC[T]] {
        def compare(x: CC[T], y: CC[T]): Int = {
          val xe = x.iterator
          val ye = y.iterator

          while (xe.hasNext && ye.hasNext) {
            val res = ord.compare(xe.next(), ye.next())
            if (res != 0) return res
          }

          Ordering.Boolean.compare(xe.hasNext, ye.hasNext)
        }
      }

    /**
     * 这个隐式转换将任何具有隐式`Ordering`的值转换为创建中缀操作的类。
     * 导入它后,您可以按如下方式编写方法:
     *
     * ```
     * def lessThan[T: Ordering](x: T, y: T) = x < y
     * ```
     */
    implicit def infixOrderingOps[T](x: T)(implicit ord: Ordering[T]): Ordering[T]#Ops = new ord.Ops(x)
  }

  /** 包含不在默认范围内的隐式对象的对象。 */
  object Implicits extends ExtraImplicits { }

  /** 根据函数`lt`构建Ordering[T]。 */
  def fromLessThan[T](cmp: (T, T) => Boolean): Ordering[T] = new Ordering[T] {
    def compare(x: T, y: T) = if (cmp(x, y)) -1 else if (cmp(y, x)) 1 else 0
    // overrides to avoid multiple comparisons
    override def lt(x: T, y: T): Boolean = cmp(x, y)
    override def gt(x: T, y: T): Boolean = cmp(y, x)
    override def gteq(x: T, y: T): Boolean = !cmp(x, y)
    override def lteq(x: T, y: T): Boolean = !cmp(y, x)
  }

  /**
   * 给定从T到S的函数f,创建一个Ordering[T],其compare函数等效于:
   *
   * ```
   * def compare(x:T, y:T) = Ordering[S].compare(f(x), f(y))
   * ```
   *
   * 这个函数类似于Ordering.on,其中Ordering[S]参数是隐式传递的。
   */
  def by[T, S](f: T => S)(implicit ord: Ordering[S]): Ordering[T] =
    fromLessThan((x, y) => ord.lt(f(x), f(y)))

  trait UnitOrdering extends Ordering[Unit] {
    def compare(x: Unit, y: Unit) = 0
  }
  implicit object Unit extends UnitOrdering

  trait BooleanOrdering extends Ordering[Boolean] {
    def compare(x: Boolean, y: Boolean) = (x, y) match {
      case (false, true) => -1
      case (true, false) => 1
      case _ => 0
    }
  }
  implicit object Boolean extends BooleanOrdering

  trait ByteOrdering extends Ordering[Byte] {
    def compare(x: Byte, y: Byte) = x.toInt - y.toInt
  }
  implicit object Byte extends ByteOrdering

  trait CharOrdering extends Ordering[Char] {
    def compare(x: Char, y: Char) = x.toInt - y.toInt
  }
  implicit object Char extends CharOrdering

  trait ShortOrdering extends Ordering[Short] {
    def compare(x: Short, y: Short) = x.toInt - y.toInt
  }
  implicit object Short extends ShortOrdering

  trait IntOrdering extends Ordering[Int] {
    def compare(x: Int, y: Int) =
      if (x < y) -1
      else if (x == y) 0
      else 1
  }
  implicit object Int extends IntOrdering

  trait LongOrdering extends Ordering[Long] {
    def compare(x: Long, y: Long) =
      if (x < y) -1
      else if (x == y) 0
      else 1
  }
  implicit object Long extends LongOrdering

  trait FloatOrdering extends Ordering[Float] {
    outer =>

    def compare(x: Float, y: Float) = java.lang.Float.compare(x, y)

    override def lteq(x: Float, y: Float): Boolean = x <= y
    override def gteq(x: Float, y: Float): Boolean = x >= y
    override def lt(x: Float, y: Float): Boolean = x < y
    override def gt(x: Float, y: Float): Boolean = x > y
    override def equiv(x: Float, y: Float): Boolean = x == y
    override def max(x: Float, y: Float): Float = math.max(x, y)
    override def min(x: Float, y: Float): Float = math.min(x, y)

    override def reverse: Ordering[Float] = new FloatOrdering {
      override def reverse = outer
      override def compare(x: Float, y: Float) = outer.compare(y, x)

      override def lteq(x: Float, y: Float): Boolean = outer.lteq(y, x)
      override def gteq(x: Float, y: Float): Boolean = outer.gteq(y, x)
      override def lt(x: Float, y: Float): Boolean = outer.lt(y, x)
      override def gt(x: Float, y: Float): Boolean = outer.gt(y, x)
      override def min(x: Float, y: Float): Float = outer.max(x, y)
      override def max(x: Float, y: Float): Float = outer.min(x, y)

    }
  }
  implicit object Float extends FloatOrdering

  trait DoubleOrdering extends Ordering[Double] {
    outer =>

    def compare(x: Double, y: Double) = java.lang.Double.compare(x, y)

    override def lteq(x: Double, y: Double): Boolean = x <= y
    override def gteq(x: Double, y: Double): Boolean = x >= y
    override def lt(x: Double, y: Double): Boolean = x < y
    override def gt(x: Double, y: Double): Boolean = x > y
    override def equiv(x: Double, y: Double): Boolean = x == y
    override def max(x: Double, y: Double): Double = math.max(x, y)
    override def min(x: Double, y: Double): Double = math.min(x, y)

    override def reverse: Ordering[Double] = new DoubleOrdering {
      override def reverse = outer
      override def compare(x: Double, y: Double) = outer.compare(y, x)

      override def lteq(x: Double, y: Double): Boolean = outer.lteq(y, x)
      override def gteq(x: Double, y: Double): Boolean = outer.gteq(y, x)
      override def lt(x: Double, y: Double): Boolean = outer.lt(y, x)
      override def gt(x: Double, y: Double): Boolean = outer.gt(y, x)
      override def min(x: Double, y: Double): Double = outer.max(x, y)
      override def max(x: Double, y: Double): Double = outer.min(x, y)
    }
  }
  implicit object Double extends DoubleOrdering

  trait BigIntOrdering extends Ordering[BigInt] {
    def compare(x: BigInt, y: BigInt) = x.compare(y)
  }
  implicit object BigInt extends BigIntOrdering

  trait BigDecimalOrdering extends Ordering[BigDecimal] {
    def compare(x: BigDecimal, y: BigDecimal) = x.compare(y)
  }
  implicit object BigDecimal extends BigDecimalOrdering

  trait StringOrdering extends Ordering[String] {
    def compare(x: String, y: String) = x.compareTo(y)
  }
  implicit object String extends StringOrdering

  trait OptionOrdering[T] extends Ordering[Option[T]] {
    def optionOrdering: Ordering[T]
    def compare(x: Option[T], y: Option[T]) = (x, y) match {
      case (None, None)       => 0
      case (None, _)          => -1
      case (_, None)          => 1
      case (Some(x), Some(y)) => optionOrdering.compare(x, y)
    }
  }
  implicit def Option[T](implicit ord: Ordering[T]): Ordering[Option[T]] =
    new OptionOrdering[T] { val optionOrdering = ord }

  implicit def Iterable[T](implicit ord: Ordering[T]): Ordering[Iterable[T]] =
    new Ordering[Iterable[T]] {
      def compare(x: Iterable[T], y: Iterable[T]): Int = {
        val xe = x.iterator
        val ye = y.iterator

        while (xe.hasNext && ye.hasNext) {
          val res = ord.compare(xe.next(), ye.next())
          if (res != 0) return res
        }

        Boolean.compare(xe.hasNext, ye.hasNext)
      }
    }

  implicit def Tuple2[T1, T2](implicit ord1: Ordering[T1], ord2: Ordering[T2]): Ordering[(T1, T2)] =
    new Ordering[(T1, T2)]{
      def compare(x: (T1, T2), y: (T1, T2)): Int = {
        val compare1 = ord1.compare(x._1, y._1)
        if (compare1 != 0) return compare1
        val compare2 = ord2.compare(x._2, y._2)
        if (compare2 != 0) return compare2
        0
      }
    }

  
  implicit def Tuple3[T1, T2, T3](implicit ord1: Ordering[T1], ord2: Ordering[T2], ord3: Ordering[T3]) : Ordering[(T1, T2, T3)] =
    new Ordering[(T1, T2, T3)]{
      def compare(x: (T1, T2, T3), y: (T1, T2, T3)): Int = {
        val compare1 = ord1.compare(x._1, y._1)
        if (compare1 != 0) return compare1
        val compare2 = ord2.compare(x._2, y._2)
        if (compare2 != 0) return compare2
        val compare3 = ord3.compare(x._3, y._3)
        if (compare3 != 0) return compare3
        0
      }
    }

  implicit def Tuple4[T1, T2, T3, T4](implicit ord1: Ordering[T1], ord2: Ordering[T2], ord3: Ordering[T3], ord4: Ordering[T4]) : Ordering[(T1, T2, T3, T4)] =
    new Ordering[(T1, T2, T3, T4)]{
      def compare(x: (T1, T2, T3, T4), y: (T1, T2, T3, T4)): Int = {
        val compare1 = ord1.compare(x._1, y._1)
        if (compare1 != 0) return compare1
        val compare2 = ord2.compare(x._2, y._2)
        if (compare2 != 0) return compare2
        val compare3 = ord3.compare(x._3, y._3)
        if (compare3 != 0) return compare3
        val compare4 = ord4.compare(x._4, y._4)
        if (compare4 != 0) return compare4
        0
      }
    }

  implicit def Tuple5[T1, T2, T3, T4, T5](implicit ord1: Ordering[T1], ord2: Ordering[T2], ord3: Ordering[T3], ord4: Ordering[T4], ord5: Ordering[T5]): Ordering[(T1, T2, T3, T4, T5)] =
    new Ordering[(T1, T2, T3, T4, T5)]{
      def compare(x: (T1, T2, T3, T4, T5), y: Tuple5[T1, T2, T3, T4, T5]): Int = {
        val compare1 = ord1.compare(x._1, y._1)
        if (compare1 != 0) return compare1
        val compare2 = ord2.compare(x._2, y._2)
        if (compare2 != 0) return compare2
        val compare3 = ord3.compare(x._3, y._3)
        if (compare3 != 0) return compare3
        val compare4 = ord4.compare(x._4, y._4)
        if (compare4 != 0) return compare4
        val compare5 = ord5.compare(x._5, y._5)
        if (compare5 != 0) return compare5
        0
      }
    }

  implicit def Tuple6[T1, T2, T3, T4, T5, T6](implicit ord1: Ordering[T1], ord2: Ordering[T2], ord3: Ordering[T3], ord4: Ordering[T4], ord5: Ordering[T5], ord6: Ordering[T6]): Ordering[(T1, T2, T3, T4, T5, T6)] =
    new Ordering[(T1, T2, T3, T4, T5, T6)]{
      def compare(x: (T1, T2, T3, T4, T5, T6), y: (T1, T2, T3, T4, T5, T6)): Int = {
        val compare1 = ord1.compare(x._1, y._1)
        if (compare1 != 0) return compare1
        val compare2 = ord2.compare(x._2, y._2)
        if (compare2 != 0) return compare2
        val compare3 = ord3.compare(x._3, y._3)
        if (compare3 != 0) return compare3
        val compare4 = ord4.compare(x._4, y._4)
        if (compare4 != 0) return compare4
        val compare5 = ord5.compare(x._5, y._5)
        if (compare5 != 0) return compare5
        val compare6 = ord6.compare(x._6, y._6)
        if (compare6 != 0) return compare6
        0
      }
    }

  implicit def Tuple7[T1, T2, T3, T4, T5, T6, T7](implicit ord1: Ordering[T1], ord2: Ordering[T2], ord3: Ordering[T3], ord4: Ordering[T4], ord5: Ordering[T5], ord6: Ordering[T6], ord7: Ordering[T7]): Ordering[(T1, T2, T3, T4, T5, T6, T7)] =
    new Ordering[(T1, T2, T3, T4, T5, T6, T7)]{
      def compare(x: (T1, T2, T3, T4, T5, T6, T7), y: (T1, T2, T3, T4, T5, T6, T7)): Int = {
        val compare1 = ord1.compare(x._1, y._1)
        if (compare1 != 0) return compare1
        val compare2 = ord2.compare(x._2, y._2)
        if (compare2 != 0) return compare2
        val compare3 = ord3.compare(x._3, y._3)
        if (compare3 != 0) return compare3
        val compare4 = ord4.compare(x._4, y._4)
        if (compare4 != 0) return compare4
        val compare5 = ord5.compare(x._5, y._5)
        if (compare5 != 0) return compare5
        val compare6 = ord6.compare(x._6, y._6)
        if (compare6 != 0) return compare6
        val compare7 = ord7.compare(x._7, y._7)
        if (compare7 != 0) return compare7
        0
      }
    }

  implicit def Tuple8[T1, T2, T3, T4, T5, T6, T7, T8](implicit ord1: Ordering[T1], ord2: Ordering[T2], ord3: Ordering[T3], ord4: Ordering[T4], ord5: Ordering[T5], ord6: Ordering[T6], ord7: Ordering[T7], ord8: Ordering[T8]): Ordering[(T1, T2, T3, T4, T5, T6, T7, T8)] =
    new Ordering[(T1, T2, T3, T4, T5, T6, T7, T8)]{
      def compare(x: (T1, T2, T3, T4, T5, T6, T7, T8), y: (T1, T2, T3, T4, T5, T6, T7, T8)): Int = {
        val compare1 = ord1.compare(x._1, y._1)
        if (compare1 != 0) return compare1
        val compare2 = ord2.compare(x._2, y._2)
        if (compare2 != 0) return compare2
        val compare3 = ord3.compare(x._3, y._3)
        if (compare3 != 0) return compare3
        val compare4 = ord4.compare(x._4, y._4)
        if (compare4 != 0) return compare4
        val compare5 = ord5.compare(x._5, y._5)
        if (compare5 != 0) return compare5
        val compare6 = ord6.compare(x._6, y._6)
        if (compare6 != 0) return compare6
        val compare7 = ord7.compare(x._7, y._7)
        if (compare7 != 0) return compare7
        val compare8 = ord8.compare(x._8, y._8)
        if (compare8 != 0) return compare8
        0
      }
    }

  implicit def Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9](implicit ord1: Ordering[T1], ord2: Ordering[T2], ord3: Ordering[T3], ord4: Ordering[T4], ord5: Ordering[T5], ord6: Ordering[T6], ord7: Ordering[T7], ord8 : Ordering[T8], ord9: Ordering[T9]): Ordering[(T1, T2, T3, T4, T5, T6, T7, T8, T9)] =
    new Ordering[(T1, T2, T3, T4, T5, T6, T7, T8, T9)]{
      def compare(x: (T1, T2, T3, T4, T5, T6, T7, T8, T9), y: (T1, T2, T3, T4, T5, T6, T7, T8, T9)): Int = {
        val compare1 = ord1.compare(x._1, y._1)
        if (compare1 != 0) return compare1
        val compare2 = ord2.compare(x._2, y._2)
        if (compare2 != 0) return compare2
        val compare3 = ord3.compare(x._3, y._3)
        if (compare3 != 0) return compare3
        val compare4 = ord4.compare(x._4, y._4)
        if (compare4 != 0) return compare4
        val compare5 = ord5.compare(x._5, y._5)
        if (compare5 != 0) return compare5
        val compare6 = ord6.compare(x._6, y._6)
        if (compare6 != 0) return compare6
        val compare7 = ord7.compare(x._7, y._7)
        if (compare7 != 0) return compare7
        val compare8 = ord8.compare(x._8, y._8)
        if (compare8 != 0) return compare8
        val compare9 = ord9.compare(x._9, y._9)
        if (compare9 != 0) return compare9
        0
      }
    }
}

sortWith sortBy sorted

/**
  * 将此$coll根据比较函数进行排序。
  * $willNotTerminateInf
  *
  * 排序是稳定的。也就是说,相等的元素(根据`lt`判断)在排序后的序列中与原始序列中的顺序相同。
  *
  * @param lt 比较函数,用于测试其第一个参数是否在所需的顺序中位于第二个参数之前。
  * @return 一个由此$coll的元素根据比较函数`lt`排序后组成的$coll。
  * @example {{{
  *   List("Steve", "Tom", "John", "Bob").sortWith(_.compareTo(_) < 0) =
  *   List("Bob", "John", "Steve", "Tom")
  * }}}
  */
def sortWith(lt: (A, A) => Boolean): Repr = sorted(Ordering fromLessThan lt)

/**
  * 根据通过将隐式给定的Ordering转换函数应用于变换为另一个域`B`的元素来对此$Coll进行排序。
  * @see [[scala.math.Ordering]]
  * $willNotTerminateInf
  * @param f 将元素映射到其他域`B`的转换函数。
  * @param ord 假设在域`B`上定义的排序。
  * @tparam B 转换`f`的目标类型,以及定义了排序`ord`的类型。
  * @return 一个由此$coll的元素根据排序`x < y`,其中`x < y`如果`ord.lt(f(x), f(y))`的排序组成的$coll。
  * @example {{{
  *   val words = "The quick brown fox jumped over the lazy dog".split(' ')
  *   // 这个例子可以工作,因为scala.Ordering将隐式提供一个Ordering[Tuple2[Int, Char]]
  *   words.sortBy(x => (x.length, x.head))
  *   res0: Array[String] = Array(The, dog, fox, the, lazy, over, brown, quick, jumped)
  * }}}
  */
def sortBy[B](f: A => B)(implicit ord: Ordering[B]): Repr = sorted(ord on f)

/**
  * 根据Ordering对此$coll进行排序。
  *
  * 排序是稳定的。也就是说,相等的元素(根据`lt`判断)在排序后的序列中与原始序列中的顺序相同。
  *
  * @see [[scala.math.Ordering]]
  *
  * @param ord 被用来比较元素的Ordering。
  * @return 一个由此$coll的元素根据排序`ord`组成的$coll。
  */
def sorted[B >: A](implicit ord: Ordering[B]): Repr = {
  val len = this.length
  val arr = new ArraySeq[A](len)
  var i = 0
  for (x <- this) {
    arr(i) = x
    i += 1
  }
  java.util.Arrays.sort(arr.array, ord.asInstanceOf[Ordering[Object]])
  val b = newBuilder
  b.sizeHint(len)
  for (x <- arr) b += x
  b.result()
}
  • 32
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BigDataMLApplication

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值