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)
posted @ 2019-03-09 15:34  刘丽刚  阅读(333)  评论(0)    收藏  举报