public void sort(Comparator<? super E> c) {
final int expectedModCount = modCount; // 当前 modCount 的值
Arrays.sort((E[]) elementData, 0, size, c); // 使用 Arrays.sort 对 elementData 数组进行排序
if (modCount != expectedModCount) { // 检查排序过程中是否发生了并发修改
throw new ConcurrentModificationException();
}
modCount++; // 增加 modCount 的值,表示进行了一次修改
}
Arrays.sort()
进入Arrays.sort()方法
public static <T> void sort(T[] a, int fromIndex, int toIndex, Comparator<? super T> c) {
if (c == null) {
sort(a, fromIndex, toIndex); // 如果比较器为 null,调用默认的排序方法
} else {
rangeCheck(a.length, fromIndex, toIndex); // 检查 fromIndex 和 toIndex 的范围是否合法
if (LegacyMergeSort.userRequested)
legacyMergeSort(a, fromIndex, toIndex, c); // 如果指定使用传统的归并排序,则调用该方法
else
TimSort.sort(a, fromIndex, toIndex, c, null, 0, 0); // 否则,调用 TimSort 进行排序
}
}
TimSort.sort
我们重点看 TimSort.sort
/**
* Sorts the given range, using the given workspace array slice
* for temp storage when possible. This method is designed to be
* invoked from public methods (in class Arrays) after performing
* any necessary array bounds checks and expanding parameters into
* the required forms.
*
* @param a the array to be sorted
* @param lo the index of the first element, inclusive, to be sorted
* @param hi the index of the last element, exclusive, to be sorted
* @param c the comparator to use
* @param work a workspace array (slice)
* @param workBase origin of usable space in work array
* @param workLen usable size of work array
* @since 1.8
*/
static <T> void sort(T[] a, int lo, int hi, Comparator<? super T> c,
T[] work, int workBase, int workLen) {
assert c != null && a != null && lo >= 0 && lo <= hi && hi <= a.length;
int nRemaining = hi - lo;
if (nRemaining < 2)
return; // 数组长度为 0 或 1 时,无需排序
// 如果数组长度较小,执行“迷你的 TimSort”而不进行合并操作
if (nRemaining < MIN_MERGE) {
int initRunLen = countRunAndMakeAscending(a, lo, hi, c);
binarySort(a, lo, hi, lo + initRunLen, c);
return;
}
/**
* 从左到右遍历数组一次,找到自然的 run,
* 将短的自然 run 扩展到 minRun 的长度,并合并 run 以保持栈的不变性。
*/
TimSort<T> ts = new TimSort<>(a, c, work, workBase, workLen);
int minRun = minRunLength(nRemaining);
do {
// 确定下一个 run
int runLen = countRunAndMakeAscending(a, lo, hi, c);
// 如果 run 很短,则扩展到 min(minRun, nRemaining) 的长度
if (runLen < minRun) {
int force = nRemaining <= minRun ? nRemaining : minRun;
binarySort(a, lo, lo + force, lo + runLen, c);
runLen = force;
}
// 将 run 推入待处理 run 栈,并可能进行合并
ts.pushRun(lo, runLen);
ts.mergeCollapse();
// 前进以找到下一个 run
lo += runLen;
nRemaining -= runLen;
} while (nRemaining != 0);
// 合并所有剩余的 run 以完成排序
assert lo == hi;
ts.mergeForceCollapse();
assert ts.stackSize == 1;
}
/**
* Examines the stack of runs waiting to be merged and merges adjacent runs
* until the stack invariants are reestablished:
* 检查等待合并的运行堆栈,并合并相邻的运行,直到满足堆栈条件:
* 1. runLen[i - 3] > runLen[i - 2] + runLen[i - 1]
* 2. runLen[i - 2] > runLen[i - 1]
*
* This method is called each time a new run is pushed onto the stack,
* so the invariants are guaranteed to hold for i < stackSize upon
* entry to the method.
* 每次将新的运行推入堆栈时,都会调用此方法,因此在进入方法时,对于 i < stackSize,满足堆栈条件。
*/
private void mergeCollapse() {
while (stackSize > 1) {
int n = stackSize - 2;
if (n > 0 && runLen[n-1] <= runLen[n] + runLen[n+1]) {
if (runLen[n - 1] < runLen[n + 1])
n--;
// 在位置 n 处合并相邻的运行
mergeAt(n);
} else if (runLen[n] <= runLen[n + 1]) {
// 在位置 n 处合并相邻的运行
mergeAt(n);
} else {
// 堆栈条件已满足,退出循环
break;
}
}
}
/**
* Merges the two runs at stack indices i and i+1. Run i must be
* the penultimate or antepenultimate run on the stack. In other words,
* i must be equal to stackSize-2 or stackSize-3.
*
* @param i stack index of the first of the two runs to merge
*/
private void mergeAt(int i) {
assert stackSize >= 2;
assert i >= 0;
assert i == stackSize - 2 || i == stackSize - 3;
int base1 = runBase[i];
int len1 = runLen[i];
int base2 = runBase[i + 1];
int len2 = runLen[i + 1];
assert len1 > 0 && len2 > 0;
assert base1 + len1 == base2;
// 记录合并后的 run 长度;如果 i 是倒数第三个 run,也要滑动最后一个 run(不参与本次合并)
runLen[i] = len1 + len2;
if (i == stackSize - 3) {
runBase[i + 1] = runBase[i + 2];
runLen[i + 1] = runLen[i + 2];
}
stackSize--;
// 找到 run2 中第一个元素在 run1 中的插入位置
int k = gallopRight(a[base2], a, base1, len1, 0, c);
assert k >= 0;
base1 += k;
len1 -= k;
if (len1 == 0)
return;
// 找到 run1 中最后一个元素在 run2 中的插入位置
len2 = gallopLeft(a[base1 + len1 - 1], a, base2, len2, len2 - 1, c);
assert len2 >= 0;
if (len2 == 0)
return;
// 使用临时数组(长度为 min(len1, len2))合并剩余的 run
if (len1 <= len2)
mergeLo(base1, len1, base2, len2);
else
mergeHi(base1, len1, base2, len2);
}