【scala原理系列】sortWith sortBy sorted Ordering 用法示例源码分析
一、概述
Ordering
是一个特质,其实例代表了一种用于对类型实例进行排序的策略。
Ordering
的伴生对象定义了许多隐式对象,用于处理AnyVal
的子类型(例如Int
、Double
)、String
和其他类型。
sortWith
、sortBy
和sorted
三个方法的工作原理:
-
**
sortWith
方法:**它使用传入的比较函数对集合进行排序。在排序过程中,根据比较函数的返回值来决定元素的顺序。如果比较函数返回true,则表示第一个参数应该排在第二个参数之前;如果返回false,则表示第一个参数应该排在第二个参数之后。通过多次应用比较函数,将集合中的元素逐步排序。这种方法实现了稳定的排序,即相等的元素在排序后的序列中与原始序列中的顺序相同。 -
sortBy
方法:它使用传入的转换函数将集合中的元素映射到另一个域,并根据转换后的值进行排序。在排序过程中,使用隐式的Ordering
对象来比较转换后的值。通过比较转换后的值,可以确定元素的顺序。这种方法也实现了稳定的排序,即相等的元素在排序后的序列中与原始序列中的顺序相同。 -
sorted
方法:它使用给定的Ordering
对象对集合进行排序。Ordering
对象定义了元素之间的比较规则。在排序过程中,通过调用Ordering
对象的compare
方法来比较元素的顺序。这种方法同样实现了稳定的排序,即相等的元素在排序后的序列中与原始序列中的顺序相同。
这三个方法都返回一个新的集合,并不会修改原始集合。它们使用的排序算法是基于数组的快速排序算法(通过java.util.Arrays.sort
方法实现)。需要注意的是,sortWith
和sorted
方法可以直接使用比较函数或Ordering
对象,而sortBy
方法需要传入一个转换函数,并依赖于隐式的Ordering
对象来进行排序。
1.内置排序
要根据一个或多个成员变量对实例进行排序,可以利用这些内置的排序方式使用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)))
2.指定compare(a: T, b: T)排序
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)
people.foreach(println)
// Person(carl,19)
// Person(bob,30)
// Person(ann,32)
这个特质和scala.math.Ordered
提供了相同的功能,但是使用不同的方式实现。类型T
可以通过扩展Ordered
来给自己赋予一种排序方式。使用Ordering
,可以以多种其他方式对同一类型进行排序。
Ordered
和Ordering
都提供了隐式转换,使它们可以互换使用。
您可以导入scala.math.Ordering.Implicits
以获取其他隐式排序方式。
二、用法
1.Ordering特质方法:
tryCompare(x: T, y: T): Option[Int]
:返回是否定义了x
和y
之间的比较,并返回compare(x, y)
的结果。compare(x: T, y: T): Int
:返回一个整数,表示x
与y
的比较结果的符号。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]
:给定一个从U
到T
的函数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
方法的结果。 -
lt
、gt
、lteq
、gteq
、equiv
方法分别返回布尔值,表示两个对象之间的比较结果。 -
max
和min
方法返回两个对象中年龄较大和较小的对象。
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()
}