最近做算法題用了Comparator接口下的compare方法,思考了一下升序和降序的規則是如何來的,現在做一個補充,方便以后回顧。
升序代碼
public static void main(String[] args) { Integer[] nums = new Integer[]{6, 8, 3, 0, 2}; Arrays.sort(nums, new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return o1 - o2; } }); for (Integer i : nums) { System.out.print(i + " "); } }
降序代碼
public static void main(String[] args) { Integer[] nums = new Integer[]{6, 8, 3, 0, 2}; Arrays.sort(nums, new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return o2 - o1; } }); for (Integer i : nums) { System.out.print(i + " "); } }
所以更多時候我們是直接記住了compare(int o1, int o2)方法 return o1 - o2 是升序,return o2 - o1 是降序。那么原因我們不妨跳進去源碼看一下
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); } }
可以看出他是進去了else內,不妨先進入legacyMergeSort看一下
private static <T> void legacyMergeSort(T[] a, Comparator<? super T> c) { T[] aux = a.clone(); if (c==null) mergeSort(aux, a, 0, a.length, 0); else mergeSort(aux, a, 0, a.length, 0, c); }
這里很明顯也是進去了else內,繼續看mergeSort
private static void mergeSort(Object[] src, Object[] dest, int low, int high, int off, Comparator c) { int length = high - low; // Insertion sort on smallest arrays if (length < INSERTIONSORT_THRESHOLD) { for (int i=low; i<high; i++) for (int j=i; j>low && c.compare(dest[j-1], dest[j])>0; j--) swap(dest, j, j-1); return; } // Recursively sort halves of dest into src int destLow = low; int destHigh = high; low += off; high += off; int mid = (low + high) >>> 1; mergeSort(dest, src, low, mid, -off, c); mergeSort(dest, src, mid, high, -off, c); // If list is already sorted, just copy from src to dest. This is an // optimization that results in faster sorts for nearly ordered lists. if (c.compare(src[mid-1], src[mid]) <= 0) { System.arraycopy(src, low, dest, destLow, length); return; } // Merge sorted halves (now in src) into dest for(int i = destLow, p = low, q = mid; i < destHigh; i++) { if (q >= high || p < mid && c.compare(src[p], src[q]) <= 0) dest[i] = src[p++]; else dest[i] = src[q++]; } }
這一段的代碼關鍵就是如下部分
if (length < INSERTIONSORT_THRESHOLD) { for (int i=low; i<high; i++) for (int j=i; j>low && c.compare(dest[j-1], dest[j])>0; j--) swap(dest, j, j-1); return; }
可以看到這里面調用了compare方法,當方法的返回值大於0的時候就將數組的前一個數和后一個數做交換。以升序為例來講解,升序的話compare方法就 return o1 - o2,那么就是 return dest[j-1] - dest[j]。
當 dest[j-1] > dest[j] 時,就進行交換。當 dest[j-1] <= dest[j] 時位置不變,從而達到數組升序。降序也是一樣的道理,就不多講了。