【java源码阅读】java.util.Collections
1. 简介
Collections
是util包中一个不可实例化(non-instantiability)
的类。
// Suppresses default constructor, ensuring non-instantiability.
private Collections() {
}
2. 源码阅读
2.1 优化参数
private static final int BINARYSEARCH_THRESHOLD = 5000;
private static final int REVERSE_THRESHOLD = 18;
private static final int SHUFFLE_THRESHOLD = 5;
private static final int FILL_THRESHOLD = 25;
private static final int ROTATE_THRESHOLD = 100;
private static final int COPY_THRESHOLD = 10;
private static final int REPLACEALL_THRESHOLD = 11;
private static final int INDEXOFSUBLIST_THRESHOLD = 35;
我们首先就可以看见Collecions定义的各种变量,这些变量叫做优化参数(Tuning Parameter),其作用在于优化类中方法的性能(permformance),之后再讲解方法时我们可以看到。
THRESHOLD
有门槛的意思
2.2 sort
@SuppressWarnings("unchecked")
用于屏蔽编译器的警告信息,比如强制类型转换时。
@SuppressWarnings("unchecked")
//<T extends Comparable<? super T>> 表示若想对list使用sort方法,那么list其中对象(或者其对象的父类)必须继承Comparable这个类,并且实现其方法。
public static <T extends Comparable<? super T>> void sort(List<T> list) {
//先将list转化为数组,再对数组进行排序。这样做的理由在于如果此list为`LinkedList`,那我们直接对其进行排序的话时间复杂度就会变为n*n*log(n)
//这里排序使用的算法是mergesort(归并排序),这需要留意mergesort是stable sort,即相等值得顺序不会改变。其他的详细解释可以参考我另一篇关于mergesort的博文。
Object[] a = list.toArray();
Arrays.sort(a);
//将排序好的结果赋值进原list
ListIterator<T> i = list.listIterator();
for (int j=0; j<a.length; j++) {
i.next();
i.set((T)a[j]);
}
}
@SuppressWarnings({"unchecked", "rawtypes"})
,rawtypes
表示类的参数上使用泛型时所出现的警告信息。
@SuppressWarnings({"unchecked", "rawtypes"})
//传入包含对象T的list及其(或其父类的)比较器Comparator
public static <T> void sort(List<T> list, Comparator<? super T> c) {
//也先转换为数组,理由同上
Object[] a = list.toArray();
Arrays.sort(a, (Comparator)c);
//同上
ListIterator<T> i = list.listIterator();
for (int j=0; j<a.length; j++) {
i.next();
i.set((T)a[j]);
}
}
2.3 binary search
此部分的函数算法都是使用二分查找实现的,其特点也和二分查找一样:
- 序列必须是有序的,无序序列不保证结果
- 若查找的元素在序列中有多个,不能保证返回的是哪一个。
//对象或其父类必须实现Comparable的方法
public static <T>
int binarySearch(List<? extends Comparable<? super T>> list, T key) {
//RandomAccess 表示list提供常数时间的元素访问方法,在这里就表明其实一个数组列表。
//如果list不是数组列表,只要其size小于BINARYSEARCH_THRESHOLD,也可以使用此搜索方法而不影响性能。
if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)
return Collections.indexedBinarySearch(list, key);
else
//size大于BINARYSEARCH_THRESHOLD的非数组列表调用此方法
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) {
// >>> 为无符号右移移位运算符。这里表示将其向右移动一位(不考虑符号位),其效果等同于“除以2”,但是性能比直接使用除法性能好。
int mid = (low + high) >>> 1;
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;
//遍历查找ListIterator的第mid个元素
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
}
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.4 reverse
//rawtypes指的是没有类型参数的泛型类或泛型接口
@SuppressWarnings({"rawtypes", "unchecked"})
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 {
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);
}
}
}
代码不难,和sort方法类似。主要的点在于一定要理解fwd
和rev
指向的位置。 如下图所示,这两个指针指向的并不是元素而是元素之间的位置,通过调用next()/previous()方法来获得其前后的元素,并将其往前/后移动一位。
Element(0) Element(1) Element(2) ... Element(n-1)
cursor positions: ^ ^ ^ ^ ^
2.5 shuffle
@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();
// Shuffle array
for (int i=size; i>1; i--)
swap(arr, i-1, rnd.nextInt(i));
ListIterator it = list.listIterator();
for (int i=0; i<arr.length; i++) {
it.next();
it.set(arr[i]);
}
}
}
2.6 swap
@SuppressWarnings({"rawtypes", "unchecked"})
public static void swap(List<?> list, int i, int j) {
//这里final表示的是l指向的对象list不能改变,但list其中的元素是可以改变的
final List l = list;
// 只需要注意一点,list的set命令会返回原先的值
l.set(i, l.set(j, l.get(i)));
}
/**
* Swaps the two specified elements in the specified array.
*/
private static void swap(Object[] arr, int i, int j) {
Object tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
__EOF__

本文作者:LinM狂想曲
本文链接:https://www.cnblogs.com/Oliver1993/p/13566105.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
本文链接:https://www.cnblogs.com/Oliver1993/p/13566105.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步