//transient修饰的变量不参与序列化和反序列化
final transient ReentrantLock lock = new ReentrantLock();// 定义一个reentrantLock锁
private transient volatile Object[] array; //定义一个volatile修饰的具有可见性和有序性的数组
final Object[] getArray() {
return array; //get方法 返回数组
}
final void setArray(Object[] a) {
array = a; //将当前的数组赋值为传入的数组
}
public CopyOnWriteArrayList() {
setArray(new Object[0]); //无参构造方法 默认创建一个 长度为0的Object数组
}
public CopyOnWriteArrayList(Collection<? extends E> c) { //有参构造方法 传入一个collections
Object[] elements; //创建一个elements数组
if (c.getClass() == CopyOnWriteArrayList.class) //判断当前传入的数组是不是一个CopyOnWriteArrayList类型的数组
elements = ((CopyOnWriteArrayList<?>)c).getArray(); //将传入的数组赋值给创建的elements数组
else {
elements = c.toArray(); //调用toarray方法 转为一个数组
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elements.getClass() != Object[].class)
elements = Arrays.copyOf(elements, elements.length, Object[].class); //如果不是Object类型数组 则复制传入elements
}
setArray(elements); //产生的elements副本存入
}
public E set(int index, E element) { //set方法 传入需要set的值以及下标
final ReentrantLock lock = this.lock; //获取当前锁
lock.lock(); //上锁
try {
Object[] elements = getArray(); //获取副本elements数组
E oldValue = get(elements, index); //根据传入的副本及下标获取需要改变的值
if (oldValue != element) { // 如果需要改变的值和 原本的值不同
int len = elements.length; //取出副本数组的数组长度
Object[] newElements = Arrays.copyOf(elements, len); //生成一个新的数组newElements 复制副本数组
newElements[index] = element; //改变newElements新数组中指定下标里的内容改为指定内容
setArray(newElements); //将产生的新数组存回array
} else {
// Not quite a no-op; ensures volatile write semantics
setArray(elements); //相同则直接将副本数组传回array
}
return oldValue; //返回被改变的值
} finally {
lock.unlock(); //解锁
}
}
public boolean add(E e) { //add方法 传入一个需要添加的数据
final ReentrantLock lock = this.lock; //获取当前锁
lock.lock(); //上锁
try {
Object[] elements = getArray(); //获取副本elements数组
int len = elements.length; //取出副本数组的数组长度
Object[] newElements = Arrays.copyOf(elements, len + 1);//生成一个新的数组newElements 复制副本数组 数组长度增加一
newElements[len] = e; //改变newElements新数组中最后一个下标里的内容为当前需要添加的内容
setArray(newElements); //相同则直接将副本数组传回array
return true; //返回true add添加成功
} finally {
lock.unlock(); //解鎖
}
}
public void add(int index, E element) { //add方法 传入一个需要添加的数据,以及指定下标
final ReentrantLock lock = this.lock; //获取当前锁
lock.lock(); //上锁
try {
Object[] elements = getArray(); //获取副本elements数组
int len = elements.length; //取出副本数组的数组长度
if (index > len || index < 0) //如果需要添加数据的下标超过数组长度或者小于零
throw new IndexOutOfBoundsException("Index: "+index+
", Size: "+len); //抛出下标越界异常
Object[] newElements; //获取副本elements数组
int numMoved = len - index;//获取一个 需要添加的下标前的位置
if (numMoved == 0) //如果是添加到第一位
newElements = Arrays.copyOf(elements, len + 1); //生成一个新的数组newElements 复制副本数组 数组长度增加一
else { //否则
newElements = new Object[len + 1]; //新建一个新的数组newElements 数组长度增加一
System.arraycopy(elements, 0, newElements, 0, index); //在新数组需要添加的下标之前数据复制
System.arraycopy(elements, index, newElements, index + 1, //在新数组需要添加的下标之后数据复制
numMoved);
}
newElements[index] = element; //将添加的新数据 放入新数组的指定下标处
setArray(newElements); //直接将副本数组传回array
} finally {
lock.unlock(); //解锁
}
}
public E remove(int index) { //remove方法 根据指定传入下标remove
final ReentrantLock lock = this.lock; //获取当前锁
lock.lock(); //上锁
try {
Object[] elements = getArray(); //获取副本elements数组
int len = elements.length; //取出副本数组的数组长度
E oldValue = get(elements, index); //根据传入的副本及下标获取需要改变的值
int numMoved = len - index - 1; //获取需要删除的下标位置
if (numMoved == 0) //如果是删除到第一位
setArray(Arrays.copyOf(elements, len - 1)); //生成一个新的数组newElements 复制副本数组 数组长度减少一
else {
Object[] newElements = new Object[len - 1];//新建一个新的数组newElements 数组长度减少一
System.arraycopy(elements, 0, newElements, 0, index);//在新数组需要删除的下标之前数据复制
System.arraycopy(elements, index + 1, newElements, index,
numMoved); //在新数组需要删除的下标之后数据复制
setArray(newElements); //直接将副本数组传回array
}
return oldValue; //返回被移除的值
} finally {
lock.unlock(); //解锁
}
}
void removeRange(int fromIndex, int toIndex) { //移除一个范围内的值
final ReentrantLock lock = this.lock; //获取当前锁
lock.lock(); //上锁
try {
Object[] elements = getArray(); //获取副本elements数组
int len = elements.length; //取出副本数组的数组长度
if (fromIndex < 0 || toIndex > len || toIndex < fromIndex) //如果开始下标小于0或者结束下标大于数组长度,或者结束下标大于开始下标
throw new IndexOutOfBoundsException(); //抛出下标越界异常
int newlen = len - (toIndex - fromIndex); //获取新数组长度
int numMoved = len - toIndex; // 获取需要移动的长度
if (numMoved == 0) //如果需要移动的长度为0
setArray(Arrays.copyOf(elements, newlen)); //复制一个原数组副本存入array
else {
Object[] newElements = new Object[newlen]; //用新数组长度新建一个数组
System.arraycopy(elements, 0, newElements, 0, fromIndex); //在移除范围开始前的复制
System.arraycopy(elements, toIndex, newElements,
fromIndex, numMoved); //从移除范围后到数组结束的复制到新数组长度为需要移动的长度
setArray(newElements);
}
} finally {
lock.unlock();
}
}
public boolean retainAll(Collection<?> c) { //传入一个集合 来保存 本集合与 传入集合的交集
if (c == null) throw new NullPointerException(); //如果传入一个空集合则空指针
final ReentrantLock lock = this.lock;//获取当前锁
lock.lock(); //上锁
try {
Object[] elements = getArray(); //获取副本elements数组
int len = elements.length; //取出副本数组的数组长度
if (len != 0) { //如果原本的数组不为0
// temp array holds those elements we know we want to keep
int newlen = 0;
Object[] temp = new Object[len]; // 创建一个数组长度为旧数组长度的数组
for (int i = 0; i < len; ++i) {
Object element = elements[i]; //遍历数组副本 获取当前下标的值
if (c.contains(element)) //如果传入的集合中有当前数组的值
temp[newlen++] = element; //则在新数组中添加交集
}
if (newlen != len) { //如果新数组长度与副本数组长度不同
setArray(Arrays.copyOf(temp, newlen)); //将新数组 set回array
return true; //返回true
}
}
return false;
} finally {
lock.unlock(); //解锁
}
}
public void clear() {
final ReentrantLock lock = this.lock; //获取当前锁
lock.lock(); //上锁
try {
setArray(new Object[0]); //array中放入一个空数组
} finally {
lock.unlock(); //解锁
}
}
public boolean addAll(int index, Collection<? extends E> c) { //将给定集合中的所有元素添加到 arraylist 中
Object[] cs = c.toArray(); //将传入的collection变为一个数组
final ReentrantLock lock = this.lock; //获取当前锁
lock.lock(); //上锁
try {
Object[] elements = getArray(); //获取副本elements数组
int len = elements.length; //取出副本数组的数组长度
if (index > len || index < 0) //如果插入下标大于数组长度或者插入下标小于0
throw new IndexOutOfBoundsException("Index: "+index+ //抛出下标越界异常
", Size: "+len);
if (cs.length == 0) //如果传入的数组长度为0
return false; //返回false
int numMoved = len - index; //获取需要移动的长度
Object[] newElements; //创建一个新的数组
if (numMoved == 0) //如果需要插入到下标为0的开始位置
newElements = Arrays.copyOf(elements, len + cs.length); //!!!! //新的数组为elements 长度为副本数组长度和需要加入的数组长度
else {
newElements = new Object[len + cs.length]; //创建新数组 长度为副本数组长度和需要加入的数组长度
System.arraycopy(elements, 0, newElements, 0, index); //将0到插入数组下标前 复制到新数组
System.arraycopy(elements, index,
newElements, index + cs.length,
numMoved); //将副本数组从插入下标开始到结束复制到新数组
}
System.arraycopy(cs, 0, newElements, index, cs.length); //将传入的数组从需要插入的下标复制到新数组
setArray(newElements); //将新数组 set回array
return true;
} finally {
lock.unlock(); //解锁
}
}
}