集合源码分析(三)Collections工具类

1、Collection和Collections有什么区别?

Collection是集合体系的最顶层,包含了集合体系的共性。

Collections是一个工具类,方法都是用于操作Collection。

2、Collections方法分析:

2.1、static void swap(List list, int i, int j) :

将指定列表中的两个索引进行位置互换。

//源码解析:
public static void swap(List<?> list, int i, int j) {
	final List l = list;
	l.set(i, l.set(j, l.get(i))); //利用set方法。设置新值会把老值返回,将返回值替换另一个
}	

2.2、static void fill(List list, Object obj) :

使用指定的对象填充指定列表的所有元素。

//源码解析:
public static <T> void fill(List<? super T> list, T obj) {
	int size = list.size();
	if (size < FILL_THRESHOLD || list instanceof RandomAccess) {
		//FILL_THRESHOLD = 25 填充的临界值/阈值
		for (int i=0; i<size; i++)
			list.set(i, obj);//从性能角度考虑
			//小于25的时候直接设置
	} else {
		ListIterator<? super T> itr = list.listIterator();
		for (int i=0; i<size; i++) {//大于25的时候利用迭代器设置
			itr.next();
			itr.set(obj);
		}
	}
}	

2.3、static void copy(List dest, List src) :

是把源列表中的数据覆盖到目标列表。

//注意:目标列表的长度至少等于源列表的长度

//源码解析:
public static <T> void copy(List<? super T> dest, List<? extends T> src) {
	int srcSize = src.size();
	if (srcSize > dest.size())//比较两者的长度
		throw new IndexOutOfBoundsException("Source does not fit in dest");
	if (srcSize < COPY_THRESHOLD ||//拷贝的性能临界值/阈值 COPY_THRESHOLD = 10
		(src instanceof RandomAccess && dest instanceof RandomAccess)) {
		for (int i=0; i<srcSize; i++)
			dest.set(i, src.get(i)); //小于10的时候直接设置
	} else {
		ListIterator<? super T> di=dest.listIterator();
		ListIterator<? extends T> si=src.listIterator();
		for (int i=0; i<srcSize; i++) {//大于10的时候利用迭代器设置
			di.next();
			di.set(si.next());
		}
	}
}

2.4、static void sort(List<T> list) :

按照列表中元素的自然顺序进行排序。

//源码解析:
public static <T extends Comparable<? super T>> void sort(List<T> list) {
	Object[] a = list.toArray();
	Arrays.sort(a);	//最终还是利用数组的排序方法
	ListIterator<T> i = list.listIterator();
	for (int j=0; j<a.length; j++) {
		i.next();
		i.set((T)a[j]);
	}
}

2.5、static void shuffle(List list):

随机置换。

//源码解析:
public static void shuffle(List<?> list, Random rnd) {
	int size = list.size();
	if (size < SHUFFLE_THRESHOLD || list instanceof RandomAccess) {
		//随机置换的性能临界值/阈值 SHUFFLE_THRESHOLD = 5
		for (int i=size; i>1; i--)
			swap(list, i-1, rnd.nextInt(i));//利用rondom
			//从后往前遍历。遍历到的数与集合中随机出来的索引上的元素进行交换。
	} else {
		//从性能考虑大于临界值/阈值5,就先转成数组。
		//随机完毕再进行赋值。
		Object arr[] = list.toArray();
		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、static void reverse(List list)  :

反转。

//源码解析:
public static void reverse(List<?> list) {
	int size = list.size();
	if (size < REVERSE_THRESHOLD || list instanceof RandomAccess) {
		//反转的性能临界值/阈值 REVERSE_THRESHOLD = 18
		for (int i=0, mid=size>>1, j=size-1; i<mid; i++, j--)
			swap(list, i, j);
			//0索引开始跟最后一个交换
			//1索引开始跟倒数第二个进行交换
			//一直循环到中间索引处。
	} 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);
		}
	}
}

2.7、static int  binarySearch(List list, Object key) :

使用二分查找法查找指定元素在指定列表的索引位置。

//二分查找。前提条件,要查询的集合必须是有序的。

自己写一个二分查找:

public static void main(String[] args) {
	ArrayList<Integer> al = new ArrayList<>();
	al.add(1);
	al.add(2);
	al.add(3);
	al.add(4);
	al.add(5);
	
	int index = getIndex(al,4);
	System.out.println(index);
	
}

private static int getIndex(ArrayList<Integer> al, int value) {
	int max = al.size() - 1;
	int min = 0;
	int mid = (max + min) /2;
	while(true){
		if(min>max){
			break;
		}
		if(al.get(mid) > value){
			max = mid - 1;
		}
		if(al.get(mid) < value){
			min = mid + 1;
		}
		if(al.get(mid) == value){
			return mid;
		}
		mid = (max + min) /2;
	}
	return -1;
}

猜你喜欢

转载自blog.csdn.net/MyronCham/article/details/82896491