FileDocCategorySizeDatePackage
CopyOnWriteArrayList.javaAPI DocAndroid 1.5 API35036Wed May 06 22:41:02 BST 2009java.util.concurrent

CopyOnWriteArrayList

public class CopyOnWriteArrayList extends Object implements Serializable, RandomAccess, List, Cloneable
Implements a {@link java.util.ArrayList} variant that is thread-safe. All write operation result in a new copy of the underlying data being created. Iterators reflect the state of the CopyOnWriteArrayList at the time they were created. They are not updated to reflect subsequent changes to the list. In addition, these iterators cannot be used for modifying the underlying CopyOnWriteArrayList.
param
the element type

Fields Summary
private static final long
serialVersionUID
private volatile transient E[]
arr
private final transient ReentrantLock
lock
Lock for the queue write methods
Constructors Summary
public CopyOnWriteArrayList()
Creates a new, empty instance of CopyOnWriteArrayList.


    // BEGIN android-added
                 
    // END android-added
      
    
public CopyOnWriteArrayList(Collection c)
Creates a new instance of CopyOnWriteArrayList and fills it with the contents of a given Collection.

param
c the collection the elements of which are to be copied into the new instance.

        this((E[]) c.toArray());
    
public CopyOnWriteArrayList(E[] array)
Creates a new instance of CopyOnWriteArrayList and fills it with the contents of a given array.

param
array the array the elements of which are to be copied into the new instance.

        int size = array.length;
        E[] data = newElementArray(size);
        for (int i = 0; i < size; i++) {
            data[i] = array[i];
        }
        arr = data;
    
Methods Summary
public booleanadd(E e)

        lock.lock();
        try {
            E[] data;
            E[] old = getData();
            int size = old.length;
            data = newElementArray(size + 1);
            System.arraycopy(old, 0, data, 0, size);
            data[size] = e;
            setData(data);
            return true;
        } finally {
            lock.unlock();
        }
    
public voidadd(int index, E e)

        lock.lock();
        try {
            E[] data;
            E[] old = getData();
            int size = old.length;
            checkIndexInclusive(index, size);
            data = newElementArray(size+1);
            System.arraycopy(old, 0, data, 0, index);
            data[index] = e;
            if (size > index) {
                System.arraycopy(old, index, data, index + 1, size - index);
            }
            setData(data);
        } finally {
            lock.unlock();
        }
    
public booleanaddAll(java.util.Collection c)

        Iterator it = c.iterator();
        int ssize = c.size();
        lock.lock();
        try {
            int size = size();
            E[] data;
            E[] old = getData();
            int nSize = size + ssize;
            data = newElementArray(nSize);
            System.arraycopy(old, 0, data, 0, size);
            while (it.hasNext()) {
                data[size++] = (E) it.next();
            }
            setData(data);
        } finally {
            lock.unlock();
        }
        return true;
    
public booleanaddAll(int index, java.util.Collection c)

        Iterator it = c.iterator();
        int ssize = c.size();
        lock.lock();
        try {
            int size = size();
            checkIndexInclusive(index, size);
            E[] data;
            E[] old = getData();
            int nSize = size + ssize;
            data = newElementArray(nSize);
            System.arraycopy(old, 0, data, 0, index);
            int i = index;
            while (it.hasNext()) {
                data[i++] = (E) it.next();
            }
            if (size > index) {
                System.arraycopy(old, index, data, index + ssize, size - index);
            }
            setData(data);
        } finally {
            lock.unlock();
        }
        return true;
    
public intaddAllAbsent(java.util.Collection c)
Adds to this CopyOnWriteArrayList all those elements from a given collection that are not yet part of the list.

param
c the collection from which the potential new elements are taken.
return
the number of elements actually added to this list.

        if (c.size() == 0) {
            return 0;
        }
        lock.lock();
        try {
            E[] old = getData();
            int size = old.length;
            E[] toAdd = newElementArray(c.size());
            int i = 0;
            for (Iterator it = c.iterator(); it.hasNext();) {
                E o = (E) it.next();
                if (indexOf(o) < 0) {
                    toAdd[i++] = o;
                }
            }
            E[] data = newElementArray(size + i);
            System.arraycopy(old, 0, data, 0, size);
            System.arraycopy(toAdd, 0, data, size, i);
            setData(data);
            return i;
        } finally {
            lock.unlock();
        }
    
public booleanaddIfAbsent(E e)
Adds to this CopyOnWriteArrayList another element, given that this element is not yet part of the list.

param
e the potential new element.
return
true if the element was added, or false otherwise.

        lock.lock();
        try {
            E[] data;
            E[] old = getData();
            int size = old.length;
            if (size != 0) {
                if (indexOf(e) >= 0) {
                    return false;
                }
            }
            data = newElementArray(size + 1);
            System.arraycopy(old, 0, data, 0, size);
            data[size] = e;
            setData(data);
            return true;
        } finally {
            lock.unlock();
        }
    
static final voidcheckIndexExlusive(int index, int size)
Throws IndexOutOfBoundsException if index is out of the list bounds. Excluding the last element.

param
index element index to check.

        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException("Index is " + index + ", size is " + size);
        }
    
static final voidcheckIndexInclusive(int index, int size)
Throws IndexOutOfBoundsException if index is out of the list bounds.

param
index element index to check.

        if (index < 0 || index > size) {
            throw new IndexOutOfBoundsException("Index is " + index + ", size is " + size);
        }
    
public voidclear()

        lock.lock();
        try {
            setData(newElementArray(0));
        } finally {
            lock.unlock();
        }
    
public java.lang.Objectclone()

        try {
            CopyOnWriteArrayList thisClone = (CopyOnWriteArrayList) super.clone();
            thisClone.setData(this.getData());
            return thisClone;
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException("CloneNotSupportedException is not expected here");
        }
    
public booleancontains(java.lang.Object o)

        return indexOf(o) >= 0;
    
public booleancontainsAll(java.util.Collection c)

        E[] data = getData();
        return containsAll(c, data, 0, data.length);
    
static final booleancontainsAll(java.util.Collection c, java.lang.Object[] data, int start, int size)
Checks if the specified range of the array contains all of the elements in the collection

param
c collection with elements
param
data array where to search the elements
param
start start index
param
size size of the range

        if (size == 0) {
            return false;
        }
        Iterator it = c.iterator();
        while (it.hasNext()) {
            Object next = it.next();
            if (indexOf(next, data, start, size) < 0) {
                return false;
            }
        }
        return true;
    
public booleanequals(java.lang.Object o)

        if (o == this) {
            return true;
        }
        if (!(o instanceof List)) {
            return false;
        }
        List l = (List) o;
        Iterator it = l.listIterator();
        Iterator ourIt = listIterator();
        while (it.hasNext()) {
            if (!ourIt.hasNext()) {
                return false;
            }
            Object thisListElem = it.next();
            Object anotherListElem = ourIt.next();
            if (!(thisListElem == null ? anotherListElem == null : thisListElem
                    .equals(anotherListElem))) {
                return false;
            }
        }
        if (ourIt.hasNext()) {
            return false;
        }
        return true;
    
public Eget(int index)

        E[] data = getData();
        return data[index];
    
final E[]getData()
gets the internal data array

return
the data array

        if (arr == null) {
            return newElementArray(0);
        }
        return arr;
    
public inthashCode()

        int hashCode = 1;
        Iterator it = listIterator();
        while (it.hasNext()) {
            Object obj = it.next();
            hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode());
        }
        return hashCode;
    
public intindexOf(E e, int index)
Returns the index of a given element, starting the search from a given position in the list.

param
e the element to search.
param
index the index at which to start the search.
return
the index of the element or null, if the element has not been found at or beyond the given start index.

        E[] data = getData();
        return indexOf(e, data, index, data.length - index);
    
public intindexOf(java.lang.Object o)

        E[] data = getData();
        return indexOf(o, data, 0, data.length);
    
static final intindexOf(java.lang.Object o, java.lang.Object[] data, int start, int size)
Returns the index in the specified range of the data array of the first occurrence of the specified element

param
o element to search
param
data array where to search
param
start start index
param
size end index
return

        if (size == 0) {
            return -1;
        }
        if (o == null) {
            for (int i = start; i < start + size; i++) {
                if (data[i] == null) {
                    return i;
                }
            }
        } else {
            for (int i = start; i < start + size; i++) {
                if (o.equals(data[i])) {
                    return i;
                }
            }
        }
        return -1;
    
public booleanisEmpty()

        return size() == 0;
    
public java.util.Iteratoriterator()

        return new ListIteratorImpl(getData(), 0);
    
public intlastIndexOf(E e, int index)
Returns the last index of a given element, starting the search from a given position in the list and going backwards.

param
e the element to search.
param
index the index at which to start the search.
return
the index of the element or null, if the element has not been found at or before the given start index.

        E[] data = getData();
        return lastIndexOf(e, data, 0, index);
    
public intlastIndexOf(java.lang.Object o)

        E[] data = getData();
        return lastIndexOf(o, data, 0, data.length);
    
static final intlastIndexOf(java.lang.Object o, java.lang.Object[] data, int start, int size)
Returns the index in the specified range of the data array of the last occurrence of the specified element

param
o element to search
param
data array where to search
param
start start index
param
size size of the range
return

        if (size == 0) {
            return -1;
        }
        if (o != null) {
            for (int i = start + size - 1; i > start - 1; i--) {
                if (o.equals(data[i])) {
                    return i;
                }
            }
        } else {
            for (int i = start + size - 1; i > start - 1; i--) {
                if (data[i] == null) {
                    return i;
                }
            }
        }
        return -1;
    
public java.util.ListIteratorlistIterator()

        return new ListIteratorImpl(getData(), 0);
    
public java.util.ListIteratorlistIterator(int index)

        E[] data = getData();
        checkIndexInclusive(index, data.length);
        return new ListIteratorImpl(data, index);
    
private final E[]newElementArray(int size)

        return (E[])new Object[size];
    
private voidreadObject(java.io.ObjectInputStream ois)
Reads the object state from the ObjectOutputStream.

param
ois ObjectInputStream to read object from.
throws
IOException if an I/O error occur.

        ois.defaultReadObject();
        int length = ois.readInt();
        if (length == 0) {
            setData(newElementArray(0));
        } else {
            E[] back = newElementArray(length);
            for (int i = 0; i < back.length; i++) {
                back[i] = (E) ois.readObject();
            }
            setData(back);
        }
    
public Eremove(int index)

        return removeRange(index, 1);
    
public booleanremove(java.lang.Object o)

        lock.lock();
        try {
            int index = indexOf(o);
            if (index == -1) {
                return false;
            }
            remove(index);
            return true;
        } finally {
            lock.unlock();
        }
    
public booleanremoveAll(java.util.Collection c)

        lock.lock();
        try {
            return removeAll(c, 0, getData().length) != 0;
        } finally {
            lock.unlock();
        }
    
final intremoveAll(java.util.Collection c, int start, int size)
Removes from the specified range of this list all the elements that are contained in the specified collection

!should be called under lock

return
Returns the number of removed elements

        int ssize = c.size();
        if (ssize == 0) {
            return 0;
        }
        Object[] old = getData();
        int arrsize = old.length;
        if (arrsize == 0) {
            return 0;
        }
        Object[] data = new Object[size];
        int j = 0;
        for (int i = start; i < (start + size); i++) {
            if (!c.contains(old[i])) {
                data[j++] = old[i];
            }
        }
        if (j != size) {
            E[] result = newElementArray(arrsize - (size - j));
            System.arraycopy(old, 0, result, 0, start);
            System.arraycopy(data, 0, result, start, j);
            System.arraycopy(old, start + size, result, start + j, arrsize
                    - (start + size));
            setData(result);
            return (size - j);
        }
        return 0;
    
EremoveRange(int start, int size)
Removes specified range from this list

        lock.lock();
        try {
            int sizeArr = size();
            checkIndexExlusive(start, sizeArr);
            checkIndexInclusive(start + size, sizeArr);
            E[] data;
            data = newElementArray(sizeArr - size);
            E[] oldArr = getData();
            System.arraycopy(oldArr, 0, data, 0, start);
            E old = oldArr[start];
            if (sizeArr > (start + size)) {
                System.arraycopy(oldArr, start + size, data, start, sizeArr
                        - (start + size));
            }
            setData(data);
            return old;
        } finally {
            lock.unlock();
        }
    
public booleanretainAll(java.util.Collection c)

        if (c == null) {
            throw new NullPointerException();
        }
        lock.lock();
        try {
            return retainAll(c, 0, getData().length) != 0;
        } finally {
            lock.unlock();
        }
    
intretainAll(java.util.Collection c, int start, int size)
Retains only the elements in the specified range of this list that are contained in the specified collection

return
Returns the number of removed elements

        Object[] old = getData();
        if (size == 0) {
            return 0;
        }
        if (c.size() == 0) {
            E[] data;
            if (size == old.length) {
                data = newElementArray(0);
            } else {
                data = newElementArray(old.length - size);
                System.arraycopy(old, 0, data, 0, start);
                System.arraycopy(old, start + size, data, start, old.length
                        - start - size);
            }
            setData(data);
            return size;
        }
        Object[] temp = new Object[size];
        int pos = 0;
        for (int i = start; i < (start + size); i++) {
            if (c.contains(old[i])) {
                temp[pos++] = old[i];
            }
        }
        if (pos == size) {
            return 0;
        }
        E[] data = newElementArray(pos + old.length - size);
        System.arraycopy(old, 0, data, 0, start);
        System.arraycopy(temp, 0, data, start, pos);
        System.arraycopy(old, start + size, data, start + pos, old.length
                - start - size);
        setData(data);
        return (size - pos);
    
public Eset(int index, E e)

        lock.lock();
        try {
            int size = size();
            checkIndexExlusive(index, size);
            E[] data;
            data = newElementArray(size);
            E[] oldArr = getData();
            System.arraycopy(oldArr, 0, data, 0, size);
            E old = data[index];
            data[index] = e;
            setData(data);
            return old;
        } finally {
            lock.unlock();
        }
    
private final voidsetData(E[] data)
sets the internal data array

param
data array to set

        arr = data;
    
public intsize()

        return getData().length;
    
public java.util.ListsubList(int fromIndex, int toIndex)

        return new SubList(this, fromIndex, toIndex);
    
public java.lang.Object[]toArray()

        E[] data = getData();
        return toArray(data, 0, data.length);
    
public T[]toArray(T[] a)

        E[] data = getData();
        return (T[]) toArray(a, data, 0, data.length);
    
static java.lang.Object[]toArray(java.lang.Object[] data, int start, int size)
Returns an array containing all of the elements in the specified range of the array in proper sequence

        Object[] result = new Object[size];
        System.arraycopy(data, start, result, 0, size);
        return result;
    
static java.lang.Object[]toArray(java.lang.Object[] to, java.lang.Object[] data, int start, int size)
Returns an array containing all of the elements in the specified range of the array in proper sequence, stores the result in the array, specified by first parameter (as for public instance method toArray(Object[] to)

        int l = data.length;
        if (to.length < l) {
            to = (Object[]) Array.newInstance(to.getClass().getComponentType(),
                    l);
        } else {
            if (to.length > l) {
                to[l] = null;
            }
        }
        System.arraycopy(data, start, to, 0, size);
        return to;
    
public java.lang.StringtoString()

        StringBuffer sb = new StringBuffer("[");

        Iterator it = listIterator();
        while (it.hasNext()) {
            sb.append(String.valueOf(it.next()));
            sb.append(", ");
        }
        if (sb.length() > 1) {
            sb.setLength(sb.length() - 2);
        }
        sb.append("]");
        return sb.toString();
    
private voidwriteObject(java.io.ObjectOutputStream oos)
Writes the object state to the ObjectOutputStream.

param
oos ObjectOutputStream to write object to.
throws
IOException if an I/O error occur.

        E[] back = getData();
        int size = back.length;
        oos.defaultWriteObject();
        oos.writeInt(size);
        for (int i = 0; i < size; i++) {
            oos.writeObject(back[i]);
        }