;Index: "+index+", Size: "+len);
12 Object[] newElements;
13 // 如果插入位置是末尾。
14 int numMoved = len - index;
15 if (numMoved == 0)
16 // 将原数组进行拷贝并扩大一个容量。
17 newElements = Arrays.copyOf(elements, len + 1);
18 else {
19 // 如果不是插入到末尾,则创建扩大一个容量的数组。
20 newElements = new Object[len + 1];
21 // 分段复制原数组,并空出指定位置。
22 System.arraycopy(elements, 0, newElements, 0, index);
23 System.arraycopy(elements, index, newElements, index + 1, numMoved);
24 }
25 // 设置指定位置的指定元素。
26 newElements[index] = element;
27 // 将array引用的地址指向新的数组。
28 setArray(newElements);
29 } finally {
30 lock.unlock();
31 }
32 }
删除元素
删除元素就是将array数组中指定位置的元素删除。
它的实现方式是,如果被删除的是最后一个元素,则直接通过Arrays.copyOf()进行处理,而不需要新建数组。否则,新建数组,然后将array数组中被删除元素之外的其它元素拷贝到新数组中。最后,将新数组赋值给array数组。
1 public E remove(int index) {
2 // 使用锁来保证线程安全。
3 final ReentrantLock lock = this.lock;
4 lock.lock();
5 try {
6 // 获得array指向的引用地址。
7 Object[] elements = getArray();
8 int len = elements.length;
9 // 根据指定的位置获取元素。
10 E oldValue = get(elements, index);
11 // 如果指定的元素是最后一个元素。
12 int numMoved = len - index - 1;
13 if (numMoved == 0)
14 // 将原数组进行拷贝截取并将array的引用地址指向新的数组。
15 setArray(Arrays.copyOf(elements, len - 1));
16 else {
17 // 如果不是最后一个元素,则创建减少一个容量的数组。
18 Object[] newElements = new Object[len - 1];
19 // 分段复制原数组,并空出指定位置。
20 System.arraycopy(elements, 0, newElements, 0, index);
21 System.arraycopy(elements, index + 1, newElements, index, numMoved);
22 // 将array的引用地址指向新的数组。
23 setArray(newElements);
24 }
25 // 返回该位置上的元素。
26 return oldValue;
27 } finally {
28 lock.unlock();
29 }
30 }
获取元素
获取元素很简单,就是返回array数组的指定位置的元素。
1 public E get(int index) {
2 return get(getArray(), index);
3 }
4
5 private E get(Object[] a, int index) {
6 return (E) a[index];
7 }
设置元素
在设置元素之前判断指定位置的旧元素是否和新元素相等,如果相等则不进行替换,但仍然要调用setArray()方法。
1 public E set(int index, E element) {
2 // 使用锁来保证线程安全。
3 final ReentrantLock lock = this.lock;
4 lock.lock();
5 try {
6 // 获得array指向的引用地址。
7 Object[] elements = getArray();
8 // 获取指定位置的旧元素。
9 E oldValue = get(elements, index);
10 // 如果旧元素的引用和新元素的引用不同。
11 if (oldValue != element) {
12 // 创建新的数组并拷贝array数组的值,替换新数组指定位置的元素。
13 int len = elements.length;
14 Object[] newElements = Arrays.copyOf(elements, len);
15 newElements[index] = element;
16 // 将array的引用地址指向新的数组
17 setArray(newElements);
18 } else {
19 // 为了确保voliatile的语义,任何一个读操作都应该是写操作的结构,所以尽管写操作没有改变数据,还是调用set方法,当然这仅仅是语义的说明,去掉也是可以的。
20 setArray(elements);
21 }
22 return oldValue;
23 } finally {
24 lock.unlock();
25 }
26 }
遍历
CopyOnWriteArrayList类的迭代方法返回的是一个COWIterator类的对象。
1 public Iterator<E> iterator() {
2 return new COWIterator<E>(getArray(), 0);
3 }
CopyOnWriteArrayList在类里维护了一个用于遍历的COWIterator类,COWIterator类实现了ListIterator接口。
1 static final class COWIterator<E> implements ListIterator<E> {
2 // 数组的快照。
3 private final Object[] snapshot;
4 // 指定下标。
5 private int cursor;
6
7 // 构造方法。
8 private COWIterator(Object[] elements, int initialCursor) {
9 cursor = initialCursor;
10 snapshot = elements;
11 }
12
13 // 判断是否存在下一个元素。
14 public boolean hasNext() {
15 return cursor < snapshot.length;
16 }
17
18 // 判断是否存在上一个元素。
19 public boolean hasPrevious() {
20 return cursor > 0;
21 }
22
23 // 获取下一个元素。
24 @SuppressWarnings("unchecked"