简体   繁体   中英

How Ordering works in Scala

I created the following class and an object which implements Ordering

//class person
class Person (s:String, i:Int, d:Date) {
  val name = s
  override def toString = name
  val age = i
  val dob = d
}
/*
logic for how to compare two Person objects. Their names will be compared first. If names are same, then their age will be compared. If their age is also same, then their date of birth will be compared. Note that we could have used any other logic to compare two person objects.
*/

implicit object myPersonOrdering extends Ordering[Person] {
  override def compare(x: Person, y: Person) = if (x.name.compareTo(y.name) == 0) {
    if (x.age.compareTo(y.age) == 0) {
      x.dob.compareTo(y.dob)
    } else (x.age.compareTo(x.age))
  } else (x.name.compareTo(y.name))

}

//create a list of Persons
val a1 = new Person("Andy",11, new Date())
val a2 = new Person("ann",12,new Date())
val a3 = new Person("Beth",31, new Date())
val a4 = new Person("Danny",10, new Date())
val a5 = new Person("peter",1, new Date())

val la = List(a1,a2,a3,a4, a5)

la.sortBy(x=>x)

I am trying to understand where the function compare is used in sortBy. Looking at source code of SeqLike.scala, the method sortBy calls method sorted which calls method java.util.Arrays.sort(arr, ord.asInstanceOf[Ordering[Object]]). Does compareTo get called in Java code?

Yes. The java.util.Arrays.sort method takes a Comparator, which Ordering extends. The compare method is called inside the TimSort algorithm used by the sort method.

The answer is "Yes". You would have understood this if you had gone bit more into the java code as well.

Here is the call in the Scala method sorted

java.util.Arrays.sort(arr, ord.asInstanceOf[Ordering[Object]])

Notice Ordering is type casted to Comparator . Java sort method takes Comparator

Here is the implementation of ordering

trait Ordering[T] extends Comparator[T] with PartialOrdering[T] with Serializable {
  outer =>
 ....
}

Notice Ordering extends Comparator .

Below is the Java sort method which takes Comparator . As Ordering is also a Comparator because Ordering extends Comparator . Ordering is passed as an argument by explicit typecasting to Comparator .

public static <T> void sort(T[] a, Comparator<? super T> c) {
    if (c == null) {
        sort(a);
    } else {
        if (LegacyMergeSort.userRequested)
            legacyMergeSort(a, c);
        else
            TimSort.sort(a, 0, a.length, c, null, 0, 0);
    }
}

Short answer : YES

If you've worked with Java before, you'll know that it contains a simillar concept to Scala's Ordering - Comparator , obviously without the implicit functionality.

Also, if you look at the definition of Ordering[T] you will see that it extends said java Comparator[T] interface.

So, on calling java.util.Arrays.sort execution proceeds exactly as if this call had come from java code using a Comparator. If you look at java.util.Arrays.sort, you will see that it in turn calls TimSort.sort- which in turns calls TimsSort.binarySort where the algorithm is actually implemented (and .compare called).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM