1. The logic of sorted method is to call java.util.Arrays.sort.
Source code:
def sorted[B >: A](implicit ord: Ordering[B]): Repr = {
val len = this.length
val b = newBuilder
if (len == 1) b ++= this
else if (len > 1) {
b.sizeHint(len)
val arr = new Array[AnyRef](len) // Previously used ArraySeq for more compact but slower code
var i = 0
for (x <- this) {
arr(i) = x.asInstanceOf[AnyRef]
i += 1
}
java.util.Arrays.sort(arr, ord.asInstanceOf[Ordering[Object]])
i = 0
while (i < arr.length) {
b += arr(i).asInstanceOf[A]
i += 1
}
}
b.result()
}
2. sortBy is the sorted method called at the end. The difference is that sortBy also needs to pass a parameter, which is a function.
源码:
def sortBy[B](f: A => B)(implicit ord: Ordering[B]): Repr = sorted(ord on f)
SortBy can pass a function, in which sorting rules can be defined, and then the elements in the list are sorted according to the passed function rules.
eg:
var lb = new ListBuffer[Int]
lb.append(1,2,9,4,5,2)
var lb2 = lb.sorted
lb2.foreach(x => println("lb2 : "+x))
println("---------------")
var sortTest = (i:Int) => {
i match {
case 1 => 2
case 2 => 1
case 4 => 0
case _ => 3
}
}
var lb3 = lb.sortBy(sortTest)
lb3.foreach(x => println("lb3: "+x))
Output:
You can see that sorted is a direct sorting, and sortedBy is a reference to the sortTest sorting method we defined
The sorting rule is that when passing in this function, there must be only one parameter of type Int, and then type matching is performed. If 4 is encountered, it is sorted according to 0, and if 2 is encountered, it is sorted according to 1.
Sorting. If you encounter 1, you will be sorted by 2, and the others will be sorted by 3, which is the largest.
2.2 Defining complex sorting rules
eg:
//create a Class Person
class Person(age:Int, salary:Double, name:String){
var Age = age
var Salary = salary
var Name = name
}
val lisa = new Person(38, 2.3, "lisa")
val nana = new Person(1, 3.4, "nana")
val zhaoSi = new Person(1, 5.9, "赵四")
val grandpa = new Person(80, 20, "grandpa")
//create a list
var listPerson = new ListBuffer[Person]
listPerson.append(lisa, nana, zhaoSi, grandpa)
//create a sort rule
var sortRule = (p:Person) => {
(p.Age, p.Salary, p.Name)
}
//list sort use the list Rule
var listPersonSorted = listPerson.sortBy(sortRule)(Ordering.Tuple3(Ordering.Int.reverse, Ordering.Double.reverse,
Ordering.String.reverse))
listPersonSorted.foreach(x => println(x.Name, x.Age, x.Salary))
Output:
Sort by age, salary, name
If you only sort by age and salary:
To
//create a Class Person
class Person(age:Int, salary:Double, name:String){
var Age = age
var Salary = salary
var Name = name
}
val lisa = new Person(38, 2.3, "lisa")
val nana = new Person(1, 3.4, "nana")
val zhaoSi = new Person(1, 5.9, "赵四")
val grandpa = new Person(80, 20, "grandpa")
//create a list
var listPerson = new ListBuffer[Person]
listPerson.append(lisa, nana, zhaoSi, grandpa)
//create a sort rule
var sortRule = (p:Person) => {
(p.Age, p.Salary)
}
//list sort use the list Rule
var listPersonSorted = listPerson.sortBy(sortRule)(Ordering.Tuple2(Ordering.Int.reverse,
Ordering.Double.reverse
))
listPersonSorted.foreach(x => println(x.Name, x.Age, x.Salary))
Edit the red part
3.sortWith is the sorted method called at the end. The difference is that sortWith needs to pass in a comparison function for comparison
def sortWith(lt: (A, A) => Boolean): Repr = sorted(Ordering fromLessThan lt)
eg:
//忽略大小写排序
def compareIngoreUpperCase(e1: String, e2: String) : Boolean = {
e1.toLowerCase < e2.toLowerCase
}
def test2() = {
val list = List( "a", "g", "F", "B", "c")
val sortWithList1 = list.sortWith(_ < _) // List(B, F, a, c, g)
val sortwithList2 = list.sortWith((left, right) => left < right) //List(B, F, a, c, g)
val sortwithList3 = list.sortWith(compareIngoreUpperCase) // List(a, B, c, F, g)
println(sortWithList1)
println(sortwithList2)
println(sortwithList3)
}