前言
印象中,Collections像是一个工具箱类,里面有着集合类的各种帮助性质的方法,如reverse()等。而Collection是集合类的上级接口,继承它的主要接口有List和Set,而List和Set的实现类也需要实现Collection定义的方法。
本文主要对Collections和Collection的区别进行介绍:
- Collections与Collection在类型上的区别
- Collections类型
- Collection类型
- Collections与Collection的常用方法
- Collections常用方法
- Collection常用方法
(若文章有不正之处,或难以理解的地方,请多多谅解,欢迎指正)
Collections与Collection在类型上的区别
Collections类型
前言提到,Collections是一个包含集合类的各种帮助性质方法的工具类,服务于Java的Collection类及其子类。
Collection类型
Collection是一个集合接口,提供了对集合对象进行基本操作的通用接口方法,有很多实现Collection接口的实现,如ArrayList、HashSet等。Collection接口的意义在于为各种具体的集合提供了最基本的统一操作方式。
Collections与Collection的方法区别
Collections常用的方法
举个简单的栗子:
public static void main(String[] args){
ArrayList<Integer> list = new ArrayList<>();
list.add(3);
list.add(1);
list.add(2);
list.add(6);
list.add(5);
list.add(4);
}
1. sort(Collection c)
对集合进行排序
public static <T extends Comparable<? super T>> void sort(List<T> list) {
list.sort(null); //直接使用list本身的sort()方法来实现排序
}
//[3, 1, 2, 6, 5, 4]
Collections.sort(list); //[1, 2, 3, 4, 5, 6]
2. shuffle(Collection c)
对集合进行随机排序
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]);
}
}
}
//[1, 2, 3, 4, 5, 6]
Collections.shuffle(list); //[2, 6, 3, 5, 1, 4]
3. reverse()
反转集合中元素的顺序
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);
}
}
}
//[3, 1, 2, 6, 5, 4]
Collections.reverse(list); //[4, 5, 6, 2, 1, 3]
4. fill(List list, Object o)
用对象o替换集合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);
} else {
ListIterator<? super T> itr = list.listIterator();
for (int i=0; i<size; i++) {
itr.next();
itr.set(obj);
}
}
}
//[3, 1, 2, 6, 5, 4]
Collections.fill(list, 0); //[0, 0, 0, 0, 0, 0]
5. copy(List m, List n)
将集合n中的元素全部复制到m中,并且覆盖相应索引的元素
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 ||
(src instanceof RandomAccess && dest instanceof RandomAccess)) {
for (int i=0; i<srcSize; i++) //将数组src中的数组复制到dest中
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());
}
}
}
//[3, 1, 2, 6, 5, 4]
List<Integer> list2 = new ArrayList<>();
list2.add(-100);
list2.add(-200);
list2.add(-300);
list2.add(-400);
list2.add(-500);
list2.add(-600);
Collections.copy(list, list2); //[-100, -200, -300, -400, -500, -600]
6. rotate(List list, int m)
集合中的元素向后移动m个位置,在后面被遮盖的元素循环到前面来
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 = distance % size;
if (distance < 0)
distance += size;
if (distance == 0)
return;
//因为可能会出现后面的数据被覆盖的可能,所以需要多一个do...while...来进行处理
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;
//根据distance与size的关系,将集合分成两段,分别进行反转,然后再将整个集合元素顺序进行反转
reverse(list.subList(0, mid));
reverse(list.subList(mid, size));
reverse(list);
}
//[3, 1, 2, 6, 5, 4]
Collections.rotate(list, 3); //[6, 5, 4, 3, 1, 2]
7. max(Collection), max(Collection, Comparator)/min(Collection), min(Collection, Comparator)
前者采用Collection内置的自然比较法,后者采用Comparator制定的比较规则进行比较
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 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)
candidate = next;
}
return candidate;
}
//[3, 1, 2, 6, 5, 4]
System.out.println(Collections.max(list)); //6
System.out.println(Collections.min(list)); //1
8. indexOfSubList(List list, List subList)
查找subList在list中首次出现的位置索引
public static int indexOfSubList(List<?> source, List<?> target) {
int sourceSize = source.size();
int targetSize = target.size();
//遍历source的次数,无需全部遍历
int maxCandidate = sourceSize - targetSize;
if (sourceSize < INDEXOFSUBLIST_THRESHOLD ||
(source instanceof RandomAccess&&target instanceof RandomAccess)) {
nextCand:
//遍历source集合
for (int candidate = 0; candidate <= maxCandidate; candidate++) {
//target集合中的元素与sourse集合中的元素进行比较
for (int i=0, j=candidate; i<targetSize; i++, j++)
if (!eq(target.get(i), source.get(j)))
continue nextCand; // Element mismatch, try next cand
return candidate; // All elements of candidate matched target
}
} else { // Iterator version of above algorithm
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
//如果ti.next()与si.next()不相等,则需要将迭代器指针位置移回source集合的首位
for (int j=0; j<i; j++)
si.previous();
continue nextCand;
}
}
return candidate;
}
}
return -1; // No candidate matched the target
}
//[3, 1, 2, 6, 5, 4]
List<Integer> list2 = new ArrayList<>();
list2.add(2);
list2.add(6);
System.out.println(Collections.indexOfSubList(list, list2)); //2
9. replaceAll(List list, Object old, Object new)
替换批定元素为某元素,若要替换的值存在则返回true,反之返回false
public static <T> boolean replaceAll(List<T> list, T oldVal, T newVal) {
boolean result = false;
int size = list.size();
//遍历集合,找到要替换的元素后进行替换操作
if (size < REPLACEALL_THRESHOLD || list instanceof RandomAccess) {
//如果替换的元素是null,则需要单独处理
if (oldVal==null) {
for (int i=0; i<size; i++) {
if (list.get(i)==null) {
list.set(i, newVal);
result = true;
}
}
} else {
for (int i=0; i<size; i++) {
if (oldVal.equals(list.get(i))) {
list.set(i, newVal);
result = true;
}
}
}
} else {
ListIterator<T> itr=list.listIterator();
//同上
if (oldVal==null) {
for (int i=0; i<size; i++) {
if (itr.next()==null) {
itr.set(newVal);
result = true;
}
}
} else {
for (int i=0; i<size; i++) {
if (oldVal.equals(itr.next())) {
itr.set(newVal);
result = true;
}
}
}
}
return result;
}
//[3, 1, 2, 6, 5, 4]
Collections.replaceAll(list, 2, 200); //[3, 1, 200, 6, 5, 4]
10. 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))); //当使用l.set()方法时会返回替换位置原先的数据
}
//[3, 1, 2, 6, 5, 4]
Collections.swap(list, 2, 5); //[3, 1, 4, 6, 5, 2]
Collection的方法
Collection是集合接口,因子类如ArrayList、LinkedList、HashSet等的底层结构不同,所以其方法实现在各子类也是有所不同,此处不进行赘述,有兴趣的朋友可以看笔者之前文章,或者关注笔者,笔者后续还会写Java集合系列的文章。
结语
其实Collections与Collection最本质的区别就在于,一个是类,一个是接口;而且它们之间的关系是,一个是工具,一个是被操作者。
本文主要对final关键字进行介绍,如果本文对你有帮助,请给一个赞吧,这会是我最大的动力~
参考资料
转载:https://blog.csdn.net/NYfor2017/article/details/105691556