CopyOnWriteArrayList简介
定義
CopyOnWriteArrayList跟ArrayList一樣實(shí)現(xiàn)了List, RandomAccess, Cloneable, Serializable接口,但是沒有繼承AbstractList。
初始化時(shí)候新建一個(gè)容量為0的數(shù)組。
add(E e)方法
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | public boolean add(E e) { //獲得鎖,添加的時(shí)候首先進(jìn)行鎖定 final ReentrantLock lock = this.lock; lock.lock(); try { //獲取當(dāng)前數(shù)組 Object[] elements = getArray(); //獲取當(dāng)前數(shù)組的長(zhǎng)度 int len = elements.length; //這個(gè)是重點(diǎn),創(chuàng)建新數(shù)組,容量為舊數(shù)組長(zhǎng)度加1,將舊數(shù)組拷貝到新數(shù)組中 Object[] newElements = Arrays.copyOf(elements, len + 1); //要添加的數(shù)據(jù)添加到新數(shù)組的末尾 newElements[len] = e; //將數(shù)組引用指向新數(shù)組,完成了添加元素操作 setArray(newElements); return true; } finally { //解鎖 lock.unlock(); } } |
從上面來說,每次添加一個(gè)新元素都會(huì)長(zhǎng)度加1,然后復(fù)制整個(gè)舊數(shù)組,由此可見對(duì)于寫多的操作,效率肯定不會(huì)很好。所以CopyOnWriteArrayList適合讀多寫少的場(chǎng)景。
add(int index, E element)方法
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | public void add(int index, E element) { //同樣也是先加鎖 final ReentrantLock lock = this.lock; lock.lock(); try { //獲取舊數(shù)組 Object[] elements = getArray(); //獲取舊數(shù)組長(zhǎng)度 int len = elements.length; //校驗(yàn)指定的index if (index > len || index < 0) throw new IndexOutOfBoundsException("Index: "+index+ ", Size: "+len); Object[] newElements; int numMoved = len - index; if (numMoved == 0)//需要插入的位置正好等于數(shù)組長(zhǎng)度,數(shù)組長(zhǎng)度加1,舊數(shù)據(jù)拷貝到新數(shù)組 newElements = Arrays.copyOf(elements, len + 1); else { //新數(shù)組長(zhǎng)度增加1 newElements = new Object[len + 1]; //分兩次拷貝,第一次拷貝舊數(shù)組0到index處的到新數(shù)組0到index,第二次拷貝舊數(shù)組index到最后的數(shù)組到新數(shù)組index+1到最后 System.arraycopy(elements, 0, newElements, 0, index); System.arraycopy(elements, index, newElements, index + 1, numMoved); } //index初插入數(shù)據(jù) newElements[index] = element; //新數(shù)組指向全局?jǐn)?shù)組 setArray(newElements); } finally { //解鎖 lock.unlock(); } } |
set(int index, E element)方法
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | public E set(int index, E element) { //修改元素之前首先加鎖 final ReentrantLock lock = this.lock; lock.lock(); try { //獲取原來的數(shù)組 Object[] elements = getArray(); //index位置的元素 E oldValue = get(elements, index); //新舊值不相等才進(jìn)行替換 if (oldValue != element) { //原來的長(zhǎng)度 int len = elements.length; //拷貝一份到新數(shù)組 Object[] newElements = Arrays.copyOf(elements, len); //替換元素 newElements[index] = element; //新數(shù)組指向全局?jǐn)?shù)組 setArray(newElements); } else { // Not quite a no-op; ensures volatile write semantics setArray(elements); } return oldValue; } finally { //解鎖 lock.unlock(); } } |
get(int index)方法
讀的時(shí)候不加鎖,代碼如下:
| 1 2 3 | public E get(int index) { return get(getArray(), index); } |
| 1 2 3 | private E get(Object[] a, int index) { return (E) a[index]; } |
remove()
remove方法不再過多介紹,看完add和set方法應(yīng)該就能理解。
迭代
內(nèi)部類COWIterator 實(shí)現(xiàn)了ListIterator接口。迭代的時(shí)候不能進(jìn)行remove,add,set等方法,會(huì)拋異常。
迭代速度快,迭代時(shí)是迭代的數(shù)組快照。
| 1 2 | /** Snapshot of the array */ private final Object[] snapshot; |
源碼分析
jdk1.7.0_71
| 1 2 3 4 5 6 | //鎖,保護(hù)所有存取器 transient final ReentrantLock lock = new ReentrantLock(); //保存數(shù)據(jù)的數(shù)組 private volatile transient Object[] array; final Object[] getArray() {return array;} final void setArray(Object[] a) {array = a;} |
空構(gòu)造,初始化一個(gè)長(zhǎng)度為0的數(shù)組
| 1 2 3 | public CopyOnWriteArrayList() { setArray(new Object[0]); } |
利用集合初始化一個(gè)CopyOnWriteArrayList
| 1 | public CopyOnWriteArrayList(Collection<? extends E> c) {} |
利用數(shù)組初始化一個(gè)CopyOnWriteArrayList
| 1 | public CopyOnWriteArrayList(E[] toCopyIn) {} |
size() 大小
| 1 | public int size() {} |
isEmpty()是否為空
| 1 | public boolean isEmpty(){} |
indexOf(Object o, Object[] elements,int index, int fence) 元素索引
| 1 | private static int indexOf(Object o, Object[] elements,int index, int fence) {} |
indexOf() 元素索引
| 1 | public int indexOf(Object o){} |
indexOf(E e, int index) 元素索引
| 1 | public int indexOf(E e, int index) {} |
lastIndexOf(Object o, Object[] elements, int index) 元素索引,最后一個(gè)
| 1 | private static int lastIndexOf(Object o, Object[] elements, int index) {} |
lastIndexOf(Object o) 元素索引,最后一個(gè)
| 1 | public int indexOf(E e, int index) {} |
lastIndexOf(E e, int index) 元素索引,最后一個(gè)
| 1 | public int lastIndexOf(E e, int index) {} |
contains(Object o) 是否包含元素
| 1 | public boolean contains(Object o){} |
clone() 淺拷貝
| 1 | public Object clone() {} |
toArray() 轉(zhuǎn)換成數(shù)組
| 1 | public Object[] toArray(){} |
toArray(T a[]) 轉(zhuǎn)換成指定類型的數(shù)組
| 1 | public <T> T[] toArray(T a[]) {} |
E get(int index)獲取指定位置的元素
| 1 | public E get(int index){} |
set(int index, E element) 指定位置設(shè)置元素
寫元素的時(shí)候,先獲得鎖,finall塊中釋放鎖
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | public E set(int index, E element) { final ReentrantLock lock = this.lock; lock.lock(); try { Object[] elements = getArray(); E oldValue = get(elements, index); if (oldValue != element) { int len = elements.length; Object[] newElements = Arrays.copyOf(elements, len); newElements[index] = element; setArray(newElements); } else { // Not quite a no-op; ensures volatile write semantics setArray(elements); } return oldValue; } finally { lock.unlock(); } } |
add(E e) 元素添加到末尾
| 1 | public boolean add(E e) {} |
add(int index, E element) 指定位置之后插入元素
| 1 | public void add(int index, E element){} |
remove(int index)刪除指定位置的元素
| 1 | public E remove(int index) {} |
remove(Object o) 刪除第一個(gè)匹配的元素
| 1 | public boolean remove(Object o) {} |
removeRange(int fromIndex, int toIndex) 刪除指定區(qū)間的元素
| 1 | private void removeRange(int fromIndex, int toIndex) {} |
addIfAbsent(E e) 如果元素不存在就添加進(jìn)list中
| 1 | public boolean addIfAbsent(E e){} |
containsAll(Collection<?> c)是否包含全部
| 1 | public boolean containsAll(Collection<?> c){} |
removeAll(Collection<?> c) 移除全部包含在集合中的元素
| 1 | public boolean removeAll(Collection<?> c){} |
retainAll(Collection<?> c) 保留指定集合的元素,其他的刪除
| 1 | public boolean retainAll(Collection<?> c){} |
addAllAbsent(Collection<? extends E> c) 如果不存在就添加進(jìn)去
| 1 | public int addAllAbsent(Collection<? extends E> c) {} |
clear() 清空list
| 1 | public void clear(){} |
addAll(Collection<? extends E> c)添加集合中的元素到尾部
| 1 | public void addAll(Collection<? extends E> c){} |
addAll(int index, Collection<? extends E> c) 添加集合中元素到指定位置之后
| 1 | public boolean addAll(int index, Collection<? extends E> c){} |
toString()
| 1 | public String toString(){} |
equals(Object o)
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public boolean equals(Object o) { if (o == this) return true; if (!(o instanceof List)) return false; List<?> list = (List<?>)(o); Iterator<?> it = list.iterator(); Object[] elements = getArray(); int len = elements.length; for (int i = 0; i < len; ++i) if (!it.hasNext() || !eq(elements[i], it.next())) return false; if (it.hasNext()) return false; return true; } |
hashCode()
| 1 | public int hashCode{} |
listIterator(final int index)和 listIterator() 返回一個(gè)迭代器,支持向前和向后遍歷
| 1 2 3 | public ListIterator<E> listIterator(final int index) {} public ListIterator<E> listIterator() {} |
iterator() 只能向后遍歷
| 1 | public Iterator<E> iterator() {} |
subList() 返回部分list
| 1 2 3 4 5 | public List<E> subList(int fromIndex, int toIndex) { ... return new COWSubList<E>(this, fromIndex, toIndex); ... } |
參考
http://www.cnblogs.com/sunwei2012/archive/2010/10/08/1845656.html
http://my.oschina.net/jielucky/blog/167198
轉(zhuǎn)載于:https://www.cnblogs.com/zhangboyu/p/7452542.html
總結(jié)
以上是生活随笔為你收集整理的CopyOnWriteArrayList简介的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【2016北京集训测试赛】river
- 下一篇: FreeMarker手册pdf