Collections 是对 Collection 和 Map 操作的一个工具类的集合
里面包含了很多的静态方法
具体解析到使用的时候可以再查文档
对于copy函数的解析
void copy(List dest,List src)
将 src 中的内容复制到 dest 中
但是拷贝的时候需要注意两个集合的大小,比如以下代码
/**
* Created By Intellij IDEA
*
* @author Xinrui Yu
* @date 2021/12/4 16:09 星期六
*/
public class Application {
public static void main(String[] args) throws Exception {
ArrayList list1 = new ArrayList();
ArrayList list2 = new ArrayList();
list1.add(123);
list1.add(456);
list1.add(789);
Collections.copy(list2,list1);
System.out.println(list2);
}
}
看似没什么问题,但是运行会发现:
查看 copy 这个方法的源代码
结合之前的知识,不难理解
因为我们初始化第二个 list 的时候,并没有对其执行 add 操作,那么其底层数组的长度其实还是为 0 的,那么自然就会抛出这样一个错误。
第一反应的解决方案是在初始化的时候,就创建一个合适长度的底层数组,比如下面这样:
翻看源码中对应的构造器,发现了问题
发现底层源码中并没有对 list 的 size 属性进行修改。
所以这种方法应该也是行不通的
那么我们就需要对 list 进行一个 “撑开”的操作。
相当于给 list2 填充了 **list1.size()**
个为 **null**
的数据,起到占位的作用。
使用Collections确保线程安全
其实底层只是在所有的方法上都使用了同步代码块包裹
package test15;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.*;
/**
* Created By Intellij IDEA
*
* @author Xinrui Yu
* @date 2021/12/4 16:09 星期六
*/
public class Application {
public static void main(String[] args){
MyThread myThread = new MyThread();
Thread thread1 = new Thread(myThread);
Thread thread2 = new Thread(myThread);
Thread thread3 = new Thread(myThread);
thread1.setName("线程1");
thread2.setName("线程2");
thread3.setName("线程3");
thread1.start();
thread2.start();
thread3.start();
}
}
class MyThread implements Runnable{
private int number = 100;
private List<Integer> list = new ArrayList<>();
private Object object = new Object();
public MyThread() {
list = Collections.synchronizedList(list);
}
@Override
public void run() {
while(true){
synchronized (object){
if(number > 0){
list.add(number);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "加入了数据:" + number);
System.out.println("当前:" + list);
number--;
}else{
break;
}
}
}
}
}