java与scala中排序
java与scala中排序
java中Arrays.sort
我们先来看Collection.sort的源码分析
Collections.sort(list);
//当list中元素是继承了Comparable的时候
public static <T extends Comparable<? super T>> void sort(List<T> list) {
list.sort(null);
}
Collections.sort(list1, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getAge() - o2.getAge();
}
});
public static <T> void sort(List<T> list, Comparator<? super T> c) {
list.sort(c);
}
//list.sort是调用了Arrays.sort()
default void sort(Comparator<? super E> c) {
Object[] a = this.toArray();
//底层也是调用了Arrays.sort
Arrays.sort(a, (Comparator) c);
ListIterator<E> i = this.listIterator();
for (Object e : a) {
i.next();
i.set((E) e);
}
}
public static <T> void sort(T[] a, Comparator<? super T> c) {
if (c == null) {
//集合中的元素继承了Comparable接口时
//底层也是调用binarySort函数
sort(a);
} else {
if (LegacyMergeSort.userRequested)
legacyMergeSort(a, c);
else
//当集合中的元素自己传递了比较对象
//底层也是调用binarySort函数
TimSort.sort(a, 0, a.length, c, null, 0, 0);
}
}
//当比较对象实现了Comparatable接口的时候
private static void binarySort(Object[] a, int lo, int hi, int start) {
assert lo <= start && start <= hi;
if (start == lo)
start++;
for ( ; start < hi; start++) {
//在这里会将比较对象强制转换成Comparable类型
Comparable pivot = (Comparable) a[start];
int left = lo;
int right = start;
assert left <= right;
while (left < right) {
int mid = (left + right) >>> 1;
//这里调用对象的compareTo方法进行比较
if (pivot.compareTo(a[mid]) < 0)
right = mid;
else
left = mid + 1;
}
assert left == right;
int n = start - left; // The number of elements to move
switch (n) {
case 2: a[left + 2] = a[left + 1];
case 1: a[left + 1] = a[left];
break;
default: System.arraycopy(a, left, a, left + 1, n);
}
a[left] = pivot;
}
}
//当容器传入了自定义比较器的时候
private static <T> void binarySort(T[] a, int lo, int hi, int start,
Comparator<? super T> c) {
assert lo <= start && start <= hi;
if (start == lo)
start++;
for ( ; start < hi; start++) {
T pivot = a[start];
int left = lo;
int right = start;
assert left <= right;
while (left < right) {
int mid = (left + right) >>> 1;
//使用自定义比较器进行比较
if (c.compare(pivot, a[mid]) < 0)
right = mid;
else
left = mid + 1;
}
assert left == right;
int n = start - left; // The number of elements to move
switch (n) {
case 2: a[left + 2] = a[left + 1];
case 1: a[left + 1] = a[left];
break;
default: System.arraycopy(a, left, a, left + 1, n);
}
a[left] = pivot;
}
}
Comparable接口
package java.lang;
import java.util.*;
public interface Comparable<T> {
public int compareTo(T o);
}
若一个类实现了Comparable接口,就意味着“该类支持排序”。既然实现了Comparable接口的类支持排序,假设现在存在“实现Comparable接口的类的对象的List列表(或数组)”,则该List列表(或数组)可以通过 Collections.sort(或 Arrays.sort)进行排序。
此外,“实现Comparable接口的类的对象”可以用作“有序映射(如TreeMap)”中的键或“有序集合(TreeSet)”中的元素,而不需要指定比较器。
Comparator接口
package java.util;
public interface Comparator<T> {
int compare(T o1, T o2);
boolean equals(Object obj);
}
若我们需要控制某个类的次序,而该类本身不支持排序(即是没有实现Comparable接口);那么,我么就可以建立一个“该类的比较器”来进行排序。这个比较器只需要实现Comparator接口即可。
scala中集合排序
sorted
/**
* 源码中需要注意地方
* 1.sorted方法中有一个隐式参数ord: Ordering
* 2.sorted方法真正排序的逻辑是调用到java.util.Arrays.sort(也就是上面分析的)
*/
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
}
/**
* 真正调用的逻辑
* trait Ordering[T] extends Comparator[T] with PartialOrdering[T] with Serializable
* 所以在这里Ordering继承了java中的Comparator接口
* trait Ordered[A] extends Any with java.lang.Comparable[A]
* 而Ordered继承了java中的Comparable接口
*/
java.util.Arrays.sort(arr, ord.asInstanceOf[Ordering[Object]])
i = 0
while (i < arr.length) {
b += arr(i).asInstanceOf[A]
i += 1
}
}
b.result()
}
实例
val list: List[String] = List("ff","bb","cc")
//自定一个隐式比较器
/**
* 当然也可以使用scala.Ordering中隐式对象
* trait StringOrdering extends Ordering[String] {
* def compare(x: String, y: String) = x.compareTo(y)
* }
* implicit object String extends StringOrdering
*/
implicit val keyOrdering = new Ordering[String] {
override def compare(x: String, y: String): Int = {
//会输出
println("=============")
y.compareTo(x)
}
}
val sorted: List[String] = list.sorted
println(sorted)
sortBy
// sortBy最后也是调用的sorted方法,不一样的地方在于,sortBy还需要提供一个属性
/**
* 并且在scala.Ordering.scala中
*
* 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)
* }
* //所以对String类型的数据会编译器会自动导入
* implicit object String extends StringOrdering寻找隐式参数ord
*/
def sortBy[B](f: A => B)(implicit ord: Ordering[B]): Repr = sorted(ord on f)
//在这里我们可以看到ord on f会使用函数f运用到compare比较中,并且返回的是一个Ordering
//如f:是取出对象中第二元素,那么我们的comapre逻辑就是根据对象的第二个元素进行比较
def on[U](f: U => T): Ordering[U] = new Ordering[U] {
def compare(x: U, y: U) = outer.compare(f(x), f(y))
}
实例
val m = Map(-2 -> 5,2 -> 6,5 -> 9,1 -> 2,0 -> -16,-1 -> -4)
m.toList.sortBy(_._2).foreach({
case (key,value) => println(key + " : " + value)
})
sortWith
//sortWith需要传入一个比较函数用来比较
def sortWith(lt: (A, A) => Boolean): Repr = sorted(Ordering fromLessThan lt)
//在这里我们可以看到Ordering fromLessThan lt的compare函数最终还是调用了我们自己传递的cmp比较器
//并且返回的还是一个Ordering类型的对象
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)
}
实例
val list: List[String] = List("a","g","F","B","c")
val sorted: List[String] = list.sortWith((e1, e2) => e1.toLowerCase < e2.toLowerCase)
println(sorted)