JDK8自帶的兩種排序 Arrays.sort和Collections.sort
Arrays.cort()是數組的排序方法,Collections.sort()是集合的排序方法,兩個方法我們在平時都經常用到,給我們帶來了便利。
一、Arrays.cort()
Arrays.sort(數組名);
Arrays.sort(數組名 ,int fromIndex, int toIndex);
這兩個方法在排序中用到的頻率最高,默認是升序排序,當我們需要默認排序時,就需要花點功夫了。
Arrays.cort()自定義排序
通過自定義一個類實現Comparator接口的compare()方法,再作爲比較器傳參,就可以現在自定義排序了。
public class test1 {
public static void main(String args[]) throws IOException {
//注意,要想改變默認的排列順序,不能使用基本類型(int,double, char),而要使用它們對應的類
Integer[] arr = {9, 8, 7, 2, 3, 4, 1, 0, 6, 5};
//定義一個自定義類MyComparator的對象
Comparator cmp = new Comparator() {
@Override
public int compare(Object o1, Object o2) {
return (Integer)o1 > (Integer)o2 ? -1 :1;
}
};
Arrays.sort(arr,cmp);
System.out.println(Arrays.toString(arr));
}
}
Arrays.cort()逆序排序
Integer[] a = {9, 8, 7, 2, 3, 4, 1, 0, 6, 5};
Arrays.sort(a,Collections.reverseOrder()); //Collections.reverseOrder()在方法調用返回一個比較器,它強行上實現Comparable接口的對象的集合的自然順序相反。
System.out.println(Arrays.toString(a));
二、Collections.cort()
List<Integer> intList = Arrays.asList(33, 24, 18, 6, 9, 99);
Collections.sort(intList);
Collections.sort()自定義排序
Collections.sort(personList, new Comparator<Person>() {
@Override
public int compare(Person p1, Person p2) {
return p1.getAge() > p2.getAge() ? 1 : -1;//升序
}
});
三、面試重點:源碼分析
一、Arrays.sort()
基本類型:採用調優的快速排序;
對象類型:採用改進的歸併排序。
1、基本類型
數組長度小於47的時候是用直接插入算法,大於47並且小於286是採用雙軸快速排序,大於286如果連續性好「也就是元素大多有序,有一個flag專門用來記錄數組元素的升降次數,代表這個數組的連續性」採用的是歸併排序,否則還是依舊採用雙軸快速排序。
小於286(小於47/大於47並且小於286)
private static void sort(int[] a, int left, int right, boolean leftmost) {
int length = right - left + 1;
// 長度小於47,使用直接插入排序
if (length < INSERTION_SORT_THRESHOLD) {
if (leftmost) {
/*
* Traditional (without sentinel) insertion sort,
* optimized for server VM, is used in case of
* the leftmost part.
*/
for (int i = left, j = i; i < right; j = ++i) {
int ai = a[i + 1];
while (ai < a[j]) {
a[j + 1] = a[j];
if (j-- == left) {
break;
}
}
a[j + 1] = ai;
}
}
//長度大於47小於286
else {
//雙軸快速排序
}
大於等於286
static void sort(int[] a, int left, int right,
int[] work, int workBase, int workLen) {
// 小於286排序
if (right - left < QUICKSORT_THRESHOLD) {
sort(a, left, right, true);
return;
}
/*
* Index run[i] is the start of i-th run
* (ascending or descending sequence).
*/
int[] run = new int[MAX_RUN_COUNT + 1];
int count = 0; run[0] = left;
//檢查數組是否接近排好序
for (int k = left; k < right; run[count] = k) {
if (a[k] < a[k + 1]) { // 上升
while (++k <= right && a[k - 1] <= a[k]);
} else if (a[k] > a[k + 1]) { // 下降
while (++k <= right && a[k - 1] >= a[k]);
for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) {
int t = a[lo]; a[lo] = a[hi]; a[hi] = t;
}
} else { // 相等
for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k]; ) {
if (--m == 0) {
sort(a, left, right, true);
return;
}
}
}
/*
*連續性不好,
*依然使用快速排序.
*/
if (++count == MAX_RUN_COUNT) {
sort(a, left, right, true);
return;
}
}
//檢查特殊情況
// Implementation note: variable "right" is increased by 1.
if (run[count] == right++) { // The last run contains one element
run[++count] = right;
} else if (count == 1) { // The array is already sorted
return;
}
/*
*連續性好,
*使用歸併排序.
*/
.............
}
}
2、對象類型
TimSort.sort()
public static void sort(Object[] a) {
if (LegacyMergeSort.userRequested)//如果設置了歸併排序爲true
legacyMergeSort(a);
else//否則使用TimeSort(結合了歸併排序和插入排序)
ComparableTimSort.sort(a, 0, a.length, null, 0, 0);
}
當待排序元素小於32個時,採用二分插入排序,是插入排序的一種改進。
當待排序元素大於等於32個時,進行歸併排序。
二、Collectiom.sort()
@SuppressWarnings({"unchecked", "rawtypes"})
default void sort(Comparator<? super E> c) {
Object[] a = this.toArray();
Arrays.sort(a, (Comparator) c);
ListIterator<E> i = this.listIterator();
for (Object e : a) {
i.next();
i.set((E) e);
}
}
使用的是Arrays.sort()中的TimSort.sort()
總結:Arrays.sort()分爲基本數據類型和對象類型。Collections.sort()是先轉換爲數組,再調用Arrays.sort(),也就是對象類型。