您的位置:首页 > 其它

Collections.sort分析

2016-04-10 22:58 239 查看
今天同学问我Collections.sort()如何实现,可惜早已忘记,回来赶紧翻代码。

测试类

public static void main(String[] args) {
List<String> strs1 = new ArrayList<>();
strs1.add("wrh");
strs1.add("swl");
strs1.add("zc");
Collections.sort(strs1);
for (String str : strs1) {
System.out.println(str);
}
}


String比较方法:

public int compareTo(String anotherString) {
int len1 = value.length;
int len2 = anotherString.value.length;
int lim = Math.min(len1, len2);
char v1[] = value;
char v2[] = anotherString.value;

int k = 0;
while (k < lim) {
char c1 = v1[k];
char c2 = v2[k];
if (c1 != c2) {
return c1 - c2;
}
k++;
}
return len1 - len2;
}


代码实现

public static <T extends Comparable<? super T>> void sort(List<T> list) {
list.sort(null);
}


方法1:

Sorts the specified list into ascending order, according to the natural ordering of its elements. All elements in the list must implement the Comparable interface. Furthermore, all elements in the list must be mutually comparable (that is, e1.compareTo(e2) must not throw a ClassCastException for any elements e1 and e2 in the list).
This sort is guaranteed to be stable: equal elements will not be reordered as a result of the sort.
The specified list must be modifiable, but need not be resizable.


意思是:把无序集合变为有序集合;集合中所有元素必须实现Comparable接口;此外,如果集合中元素类型不同在调用compareTo方法时会抛出ClassCastException异常;如果在排序时向集合中添加元素,则报ConcurrentModificationException错误。

public static <T> void sort(List<T> list, Comparator<? super T> c) {
list.sort(c);
}


方法2:

Sorts the specified list according to the order induced by the specified comparator. All elements in the list must be mutually comparable using the specified comparator (that is, c.compare(e1, e2) must not throw a ClassCastException for any elements e1 and e2 in the list).
This sort is guaranteed to be stable: equal elements will not be reordered as a result of the sort.
The specified list must be modifiable, but need not be resizable.


意思是:根据指定comparator来对集合进行排序;集合中所有元素根据指定的comparator来进行排序。

list.sort方法

sort方法中调用的是list对象中的sort方法;我们以ArrayList方法中的sort方法。

public void sort(Comparator<? super E> c) {
final int expectedModCount = modCount;
Arrays.sort((E[]) elementData, 0, size, c);//排序是对数组进行操作的
if (modCount != expectedModCount) {//如果在排序时向集合中添加元素,抛出异常
throw new ConcurrentModificationException();
}
modCount++;
}


Arrays.sort方法

public static <T> void sort(T[] a, int fromIndex, int toIndex,
Comparator<? super T> c) {
if (c == null) {//如果没有比较器
sort(a, fromIndex, toIndex);
} else {
rangeCheck(a.length, fromIndex, toIndex);//边界检测
if (LegacyMergeSort.userRequested)//根据配置选择排序方法
legacyMergeSort(a, fromIndex, toIndex, c);
else
TimSort.sort(a, fromIndex, toIndex, c, null, 0, 0);
}
}


1.legacyMergeSort方法

private static <T> void legacyMergeSort(T[] a, int fromIndex, int toIndex,
Comparator<? super T> c) {
T[] aux = copyOfRange(a, fromIndex, toIndex);//首先复制数组
if (c==null)//是否有比较器
mergeSort(aux, a, fromIndex, toIndex, -fromIndex);
else
mergeSort(aux, a, fromIndex, toIndex, -fromIndex, c);
}


查看排序方法:

private static void mergeSort(Object[] src,
Object[] dest,
int low, int high, int off,
Comparator c) {
int length = high - low;

//当数组长度小于7时取出最大值放在最左边
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;
}

//大于7使用归并排序
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 (c.compare(src[mid-1], src[mid]) <= 0) {
System.arraycopy(src, low, dest, destLow, length);
return;
}

//把src数组合并到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++];
}
}


2.TimSort.sort方法

TimSort 是一个归并排序做了大量优化的版本。对归并排序排在已经反向排好序的输入时表现O(n^2)的特点做了特别优化。对已经正向排好序的输入减少回溯。

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;  // Arrays of size 0 and 1 are always sorted

// If array is small, do a "mini-TimSort" with no merges
if (nRemaining < MIN_MERGE) {
int initRunLen = countRunAndMakeAscending(a, lo, hi, c);
binarySort(a, lo, hi, lo + initRunLen, c);
return;
}

/**
* March over the array once, left to right, finding natural runs,
* extending short natural runs to minRun elements, and merging runs
* to maintain stack invariant.
*/
TimSort<T> ts = new TimSort<>(a, c, work, workBase, workLen);
int minRun = minRunLength(nRemaining);
do {
// Identify next run
int runLen = countRunAndMakeAscending(a, lo, hi, c);

// If run is short, extend to min(minRun, nRemaining)
if (runLen < minRun) {
int force = nRemaining <= minRun ? nRemaining : minRun;
binarySort(a, lo, lo + force, lo + runLen, c);
runLen = force;
}

// Push run onto pending-run stack, and maybe merge
ts.pushRun(lo, runLen);
ts.mergeCollapse();

// Advance to find next run
lo += runLen;
nRemaining -= runLen;
} while (nRemaining != 0);

// Merge all remaining runs to complete sort
assert lo == hi;
ts.mergeForceCollapse();
assert ts.stackSize == 1;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  arraylist