Collections源码分析(持续更新)
1.排序sort
/**
* Sorts the specified list into ascending order, according to the
* {@linkplain Comparable natural ordering} of its elements.
* All elements in the list must implement the {@link Comparable}
* interface. Furthermore, all elements in the list must be
* <i>mutually comparable</i> (that is, {@code e1.compareTo(e2)}
* must not throw a {@code ClassCastException} for any elements
* {@code e1} and {@code e2} in the list).
*
* <p>This sort is guaranteed to be <i>stable</i>: equal elements will
* not be reordered as a result of the sort.
*
* <p>The specified list must be modifiable, but need not be resizable.
*
* @implNote
* This implementation defers to the {@link List#sort(Comparator)}
* method using the specified list and a {@code null} comparator.
*
* @param <T> the class of the objects in the list
* @param list the list to be sorted.
* @throws ClassCastException if the list contains elements that are not
* <i>mutually comparable</i> (for example, strings and integers).
* @throws UnsupportedOperationException if the specified list's
* list-iterator does not support the {@code set} operation.
* @throws IllegalArgumentException (optional) if the implementation
* detects that the natural ordering of the list elements is
* found to violate the {@link Comparable} contract
* @see List#sort(Comparator)
*/
@SuppressWarnings("unchecked")
public static <T extends Comparable<? super T>> void sort(List<T> list) {
list.sort(null);
}
/**
* Sorts the specified list according to the order induced by the
* specified comparator. All elements in the list must be <i>mutually
* comparable</i> using the specified comparator (that is,
* {@code c.compare(e1, e2)} must not throw a {@code ClassCastException}
* for any elements {@code e1} and {@code e2} in the list).
*
* <p>This sort is guaranteed to be <i>stable</i>: equal elements will
* not be reordered as a result of the sort.
*
* <p>The specified list must be modifiable, but need not be resizable.
*
* @implNote
* This implementation defers to the {@link List#sort(Comparator)}
* method using the specified list and comparator.
*
* @param <T> the class of the objects in the list
* @param list the list to be sorted.
* @param c the comparator to determine the order of the list. A
* {@code null} value indicates that the elements' <i>natural
* ordering</i> should be used.
* @throws ClassCastException if the list contains elements that are not
* <i>mutually comparable</i> using the specified comparator.
* @throws UnsupportedOperationException if the specified list's
* list-iterator does not support the {@code set} operation.
* @throws IllegalArgumentException (optional) if the comparator is
* found to violate the {@link Comparator} contract
* @see List#sort(Comparator)
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public static <T> void sort(List<T> list, Comparator<? super T> c) {
list.sort(c);
}
1.1唯一的区别:第一个不带Comparator接口,第二个带Comparator接口
1.2共同点:
a.相同的元素不会重新排序
b.指定的列表必须可修改,但不需要调整大小。
c.可能抛出的异常
@throws ClassCastException
@throws UnsupportedOperationException
@throws IllegalArgumentException
1.3ArrayList排序原理
public void sort(Comparator<? super E> c) {
final int expectedModCount = modCount;
Arrays.sort((E[]) elementData, 0, size, c);//排序功能交给Arrays
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();// 可能导致并发修改异常
}
modCount++;
}
public static <T> void sort(T[] a, int fromIndex, int toIndex,
Comparator<? super T> c) {
if (c == null) {
sort(a, fromIndex, toIndex);// 不传比较器,默认升序
} else {
// 校验:0<=起始位置<=结束位置<=列表长度-1
rangeCheck(a.length, fromIndex, toIndex);
if (LegacyMergeSort.userRequested)// 默认false
legacyMergeSort(a, fromIndex, toIndex, c);// MergeSort归并排序
else
// java8引入
TimSort.sort(a, fromIndex, toIndex, c, null, 0, 0);// 排序规则交给TimSort
}
}
重点是这个: TimSort.sort(a, fromIndex, toIndex, c, null, 0, 0);// 排序规则交给TimSort
This implementation was adapted from Tim Peters's list sort for Python
/**
* 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; // 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;
}
还是借助binarySort(a, lo, lo + force, lo + runLen, c);
1.4 Timsort的核心过程
TimSort 算法为了减少对升序部分的回溯和对降序部分的性能倒退,将输入按其升序和降序特点进行了分区。排序的输入的单位不是一个个单独的数字,而是一个个的块-分区。其中每一个分区叫一个run。针对这些 run 序列,每次拿一个 run 出来按规则进行合并。每次合并会将两个 run合并成一个 run。合并的结果保存到栈中。合并直到消耗掉所有的 run,这时将栈上剩余的 run合并到只剩一个 run 为止。这时这个仅剩的 run 便是排好序的结果。
综上述过程,Timsort算法的过程包括
(0)如何数组长度小于某个值,直接用二分插入排序算法
(1)找到各个run,并入栈
(2)按规则合并run
2.二分查找binarySearch
2.1 方法如下
方法一:public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key)
方法二:public static <T> int binarySearch(List<? extends T> list, T key, Comparator<? super T> c)
主要区别:带不带Comparator<? super T> c
2.2 以方法一public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key)为例子
public static <T>
int binarySearch(List<? extends Comparable<? super T>> list, T key) {
if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)
return Collections.indexedBinarySearch(list, key);// 索引方式
else
return Collections.iteratorBinarySearch(list, key);// 迭代器方式
}
private static <T>
int indexedBinarySearch(List<? extends Comparable<? super T>> list, T key) {
int low = 0;
int high = list.size()-1;
while (low <= high) {
int mid = (low + high) >>> 1;// 右移动一位,相当于(low + high) / 2
Comparable<? super T> midVal = list.get(mid);// 中间位置的值
int cmp = midVal.compareTo(key);
if (cmp < 0) // 大于中间位置的值
low = mid + 1;
else if (cmp > 0) // 小于中间位置的值
high = mid - 1;
else // 等于中间位置的值
return mid; // key found
}
return -(low + 1); // key not found
}
private static <T>
int iteratorBinarySearch(List<? extends Comparable<? super T>> list, T key)
{
int low = 0;
int high = list.size()-1;
// 迭代器方式
ListIterator<? extends Comparable<? super T>> i = list.listIterator();
// 下面的代码跟前面代码一样
while (low <= high) {
int mid = (low + high) >>> 1;
// 迭代器方式获取中间值
Comparable<? super T> midVal = get(i, mid);
int cmp = midVal.compareTo(key);
if (cmp < 0)
low = mid + 1;
else if (cmp > 0)
high = mid - 1;
else
return mid; // key found
}
return -(low + 1); // key not found
}
/**
* Gets the ith element from the given list by repositioning the specified
* list listIterator.
*/
private static <T> T get(ListIterator<? extends T> i, int index) {
T obj = null;
int pos = i.nextIndex();
if (pos <= index) {
do {
obj = i.next();
} while (pos++ < index);
} else {
do {
obj = i.previous();
} while (--pos > index);
}
return obj;
}
2.3 通过上面的代码可以分析,ArrayList适合二分查找(能快速获取到中间index);反之,LinkedList不适合。
3.有序列表翻转
3.1 例如:1 3 5 7 8 ===》 8 7 5 3 1
3.2 源码分析
public static void reverse(List<?> list) {
int size = list.size();
if (size < REVERSE_THRESHOLD || list instanceof RandomAccess) {
for (int i=0, mid=size>>1, j=size-1; i<mid; i++, j--)
swap(list, i, j);
} else {
// instead of using a raw type here, it's possible to capture
// the wildcard but it will require a call to a supplementary
// private method
ListIterator fwd = list.listIterator();// 迭代器第一个
ListIterator rev = list.listIterator(size);// 迭代器最后一个
for (int i=0, mid=list.size()>>1; i<mid; i++) {// 交换
Object tmp = fwd.next();
fwd.set(rev.previous());
rev.set(tmp);
}
}
}
4.打乱列表
// 默认的随机策略
public static void shuffle(List<?> list) {
Random rnd = r;
if (rnd == null)
r = rnd = new Random(); // harmless race.
shuffle(list, rnd);
}
// 传人指定的随机策略
@SuppressWarnings({"rawtypes", "unchecked"})
public static void shuffle(List<?> list, Random rnd) {
int size = list.size();
if (size < SHUFFLE_THRESHOLD || list instanceof RandomAccess) {
for (int i=size; i>1; i--)// 最后一个元素每次和前面随机的元素交换
swap(list, i-1, rnd.nextInt(i));
} else {
// 借助数组
Object arr[] = list.toArray();
// 打乱数组
for (int i=size; i>1; i--)// 最后一个元素每次和前面随机的元素交换
swap(arr, i-1, rnd.nextInt(i));
// 打乱的插入回list
ListIterator it = list.listIterator();
for (int i=0; i<arr.length; i++) {
it.next();
it.set(arr[i]);
}
}
}
5.用指定的对象填充list
public static <T> void fill(List<? super T> list, T obj) {
int size = list.size();
if (size < FILL_THRESHOLD || list instanceof RandomAccess) {
for (int i=0; i<size; i++)
list.set(i, obj);// list元素全变成了obj
} else {
ListIterator<? super T> itr = list.listIterator();
for (int i=0; i<size; i++) {
itr.next();
itr.set(obj);// list元素全变成了obj
}
}
}
6.集合复制
public static <T> void copy(List<? super T> dest, List<? extends T> src) {
int srcSize = src.size();
if (srcSize > dest.size())// 限制目标集合的size要足够大
throw new IndexOutOfBoundsException("Source does not fit in dest");
if (srcSize < COPY_THRESHOLD ||
(src instanceof RandomAccess && dest instanceof RandomAccess)) {
for (int i=0; i<srcSize; i++)
dest.set(i, src.get(i));// 指定位置复制
} else {
ListIterator<? super T> di=dest.listIterator();
ListIterator<? extends T> si=src.listIterator();
// 迭代器方式赋值
for (int i=0; i<srcSize; i++) {
di.next();
di.set(si.next());
}
}
}
7.获取集合的最小和最大值
public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> coll) {
Iterator<? extends T> i = coll.iterator();// 迭代器的方式,兼容所有集合类
T candidate = i.next();
while (i.hasNext()) {
T next = i.next();
if (next.compareTo(candidate) < 0)// 比较大小用compareTo
candidate = next;
}
return candidate;
}
// min的第二种方式
public static <T> T min(Collection<? extends T> coll, Comparator<? super T> comp) {
if (comp==null)
return (T)min((Collection) coll);
Iterator<? extends T> i = coll.iterator();
T candidate = i.next();
while (i.hasNext()) {
T next = i.next();
if (comp.compare(next, candidate) < 0)
candidate = next;
}
return candidate;
}
public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll) {
Iterator<? extends T> i = coll.iterator();
T candidate = i.next();
while (i.hasNext()) {
T next = i.next();
if (next.compareTo(candidate) > 0)
candidate = next;
}
return candidate;
}
public static <T> T max(Collection<? extends T> coll, Comparator<? super T> comp) {
if (comp==null)
return (T)max((Collection) coll);
Iterator<? extends T> i = coll.iterator();
T candidate = i.next();
while (i.hasNext()) {
T next = i.next();
if (comp.compare(next, candidate) > 0)
candidate = next;
}
return candidate;
}
8.按指定的距离旋转
public static void rotate(List<?> list, int distance) {
if (list instanceof RandomAccess || list.size() < ROTATE_THRESHOLD)
rotate1(list, distance);
else
rotate2(list, distance);
}
private static <T> void rotate1(List<T> list, int distance) {
int size = list.size();
if (size == 0)
return;
distance = distance % size;
if (distance < 0)
distance += size;
if (distance == 0)
return;
for (int cycleStart = 0, nMoved = 0; nMoved != size; cycleStart++) {
T displaced = list.get(cycleStart);
int i = cycleStart;
do {
i += distance;
if (i >= size)
i -= size;
displaced = list.set(i, displaced);
nMoved ++;
} while (i != cycleStart);
}
}
private static void rotate2(List<?> list, int distance) {
int size = list.size();
if (size == 0)
return;
int mid = -distance % size;
if (mid < 0)
mid += size;
if (mid == 0)
return;
// 这三个方法说了此方法的目的
reverse(list.subList(0, mid));
reverse(list.subList(mid, size));
reverse(list);
}
下面演示了此方法的作用
9.返回子列表的在父列表的第一次位置和最后一次位置
public static int indexOfSubList(List<?> source, List<?> target) {
int sourceSize = source.size();
int targetSize = target.size();
int maxCandidate = sourceSize - targetSize;// 最大的候选位置
if (sourceSize < INDEXOFSUBLIST_THRESHOLD ||
(source instanceof RandomAccess&&target instanceof RandomAccess)) {
nextCand:
for (int candidate = 0; candidate <= maxCandidate; candidate++) {
for (int i=0, j=candidate; i<targetSize; i++, j++)
if (!eq(target.get(i), source.get(j)))
continue nextCand; // 元素不匹配,跳到最外层for
return candidate; // 只有匹配了,才会走这行
}
} else { // 算法一致,只是迭代器方法
ListIterator<?> si = source.listIterator();
nextCand:
for (int candidate = 0; candidate <= maxCandidate; candidate++) {
ListIterator<?> ti = target.listIterator();
for (int i=0; i<targetSize; i++) {
if (!eq(ti.next(), si.next())) {
// Back up source iterator to next candidate
for (int j=0; j<i; j++)
si.previous();
continue nextCand;
}
}
return candidate;
}
}
return -1; // 没有匹配目标方法
}
public static int lastIndexOfSubList(List<?> source, List<?> target) {
int sourceSize = source.size();
int targetSize = target.size();
int maxCandidate = sourceSize - targetSize;
if (sourceSize < INDEXOFSUBLIST_THRESHOLD ||
source instanceof RandomAccess) { // Index access version
nextCand:
for (int candidate = maxCandidate; candidate >= 0; candidate--) {//反向匹配,其他都一样
for (int i=0, j=candidate; i<targetSize; i++, j++)
if (!eq(target.get(i), source.get(j)))
continue nextCand;
return candidate;
}
} else { // Iterator version of above algorithm
if (maxCandidate < 0)
return -1;
ListIterator<?> si = source.listIterator(maxCandidate);
nextCand:
for (int candidate = maxCandidate; candidate >= 0; candidate--) {
ListIterator<?> ti = target.listIterator();
for (int i=0; i<targetSize; i++) {
if (!eq(ti.next(), si.next())) {
if (candidate != 0) {
// Back up source iterator to next candidate
for (int j=0; j<=i+1; j++)
si.previous();
}
continue nextCand;
}
}
return candidate;
}
}
return -1; // No candidate matched the target
}
10.包装成只读、不可修改的集合(unmodifiableXXXX)
操作方法,抛异常
11.包装集合为线程安全(synchronizedXXXX)
方法加synchronized(mutex) mutex是代表当前对象