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;
}