最近写过一个界面,涉及到排序。
用到了 Collections 中的 sort 方法:
1 | Collections.sort(mData, new Comparator<BookMemberReport>() { |
Collections 根据传入的 Comparator 进行排序。刚开始写的时候通过不停的试,把正确的结果给试出来了。但是对于其原理却不是很清晰,今天便稍微扒一扒其源码。
1 | public static <T> void sort(List<T> list, Comparator<? super T> c) { |
跟到 Arrays.sort() 方法:
1 | public static <T> void sort(T[] a, Comparator<? super T> c) { |
在 else 分支中还有一个分支,看到 userRequested:
1 | /** |
所以所有的排序应该都是走的 TimSort 分支。但是这不影响研究 Comparator 接口的原理,进入到 legacyMergeSort:
1 | /** To be removed in a future release. */ |
继续跟进:
1 | /** |
看到第一个 if 语句,看到 INSERTIONSORT_THRESHOLD 变量:
1 | /** |
即只要是数组个数小于 7 的,直接走 if 语句进行排序,然后返回。重点:
1 | for (int i=low; i<high; i++) |
即第 j-1 个元素跟 j 进行比较,通过 compare 返回的值,如果大于 0,则进行交换。看到 compare 接口:
1 | /** |
所以很清晰了,如果 compare 返回的值大于 0,那么就会将这 2 个元素交换,即将大元素放在前面进行降序,反之则是正序。
文中代码基于 Android-25,Android-26 中已经剔除 LegacyMergeSort。
1 | public static <T> void sort(T[] a, Comparator<? super T> c) { |
虽然分析选取的代码并不会执行,但是丝毫不影响研究 Comparator 的原理。无论源码怎么变化,只要 Comparator 接口不变,那么它的原理便会始终是这样的。抛弃复杂的,选取简单的,使源码阅读起来更为快捷。好了,简单的阅读完了,可以阅读一下复杂的 TimSort.sort 了。