remove, add etc..) operation
 * is performed.O(n) or worse,
 * but traversal operations are fast and efficient, especially when running in
 * a multi-thread environment without the need to design complex synchronize
 * mechanisms.Iterators in this class work on a snapshot of the backing store
 * at the moment the iterator itself was created, hence the iterator will not
 * reflect changes in the underlying storage. Thus, update operation on the
 * Iterators are not supported, but as interferences from other
 * threads are impossible, no ConcurrentModificationException
 * will be ever thrown from within the Iterator.
 * 
 *
 * CopyOnWriteArrayList listeners =
 *   new CopyOnWriteArrayList();
 *
 * [...]
 *
 * for (final EventListener listener : listeners)
 *   {
 *     Runnable dispatcher = new Runnable() {
 *       public void run()
 *       {
 *         listener.preferenceChange(event);
 *       }
 *     };
 *
 *     Executor executor = Executors.newSingleThreadExecutor();
 *     executor.execute(dispatcher);
 *   }
 *   
index at which
   * e appears in this List, or -1 if it does not
   * appear.
   *
   * @param e the element whose inclusion in the list is being tested
   * @param index the index at which the search begins
   * @return the index where e was found
   */
  public int indexOf(E e, int index)
  {
    E[] data = this.data;
    for (int i = index; i < data.length; i++)
      if (equals(e, data[i]))
        return i;
    return -1;
  }
  /**
   * Returns the highest index at which element appears in this List, or -1 if
   * it does not appear.
   *
   * @param e
   *          the element whose inclusion in the List is being tested
   * @return the index where e was found
   */
  public int lastIndexOf(Object e)
  {
    E[] data = this.data;
    for (int i = data.length - 1; i >= 0; i--)
      if (equals(e, data[i]))
        return i;
    return -1;
  }
  /**
   * Returns the highest index lesser equal index at
   * which e appears in this List, or -1 if it does not
   * appear.
   *
   * @param e the element whose inclusion in the list is being tested
   * @param index the index at which the search begins
   * @return the index where e was found
   */
  public int lastIndexOf(E e, int index)
  {
    E[] data = this.data;
    for (int i = index; i >= 0; i--)
      if (equals(e, data[i]))
        return i;
    return -1;
  }
  /**
   * Creates a shallow copy of this ArrayList (elements are not cloned).
   *
   * @return the cloned object
   */
  public Object clone()
  {
    CopyOnWriteArrayListtrue if the object was removed, false
   * otherwise.
   *
   * @param element the object to be removed.
   * @return true if element was removed, false otherwise. false means also that
   * the underlying storage was unchanged after this operation concluded.
   */
  public synchronized boolean remove(Object element)
  {
    E[] snapshot = this.data;
    int len = snapshot.length;
    if (len == 0)
      return false;
    E[] newData = (E[]) new Object[len - 1];
    // search the element to remove while filling the backup array
    // this way we can run this method in O(n)
    int elementIndex = -1;
    for (int i = 0; i < snapshot.length; i++)
      {
        if (equals(element, snapshot[i]))
          {
            elementIndex = i;
            break;
          }
        if (i < newData.length)
          newData[i] = snapshot[i];
      }
    if (elementIndex < 0)
      return false;
    System.arraycopy(snapshot, elementIndex + 1, newData, elementIndex,
                     snapshot.length - elementIndex - 1);
    this.data = newData;
    return true;
  }
  /**
   * Removes all the elements contained in the given collection.
   * This method removes the elements that are contained in both
   * this list and in the given collection.
   *
   * @param c the collection containing the elements to be removed from this
   * list.
   * @return true if at least one element was removed, indicating that
   * the list internal storage changed as a result, false otherwise.
   */
  public synchronized boolean removeAll(Collection> c)
  {
    if (c.size() == 0)
      return false;
    E [] snapshot = this.data;
    E [] storage = (E[]) new Object[this.data.length];
    boolean changed = false;
    int length = 0;
    for (E element : snapshot)
      {
        // copy all the elements, including null values
        // if the collection can hold it
        // FIXME: slow operation
        if (c.contains(element))
          changed = true;
        else
          storage[length++] = element;
      }
    if (!changed)
      return false;
    E[] newData = (E[]) new Object[length];
    System.arraycopy(storage, 0, newData, 0, length);
    this.data = newData;
    return true;
  }
  /**
   * Removes all the elements that are not in the passed collection.
   * If the collection is void, this method has the same effect of
   * clear().
   * Please, note that this method is extremely slow (unless the argument has
   * size == 0) and has bad performance is both space and time
   * usage.
   *
   * @param c the collection containing the elements to be retained by this
   * list.
   * @return true the list internal storage changed as a result of this
   * operation, false otherwise.
   */
  public synchronized boolean retainAll(Collection> c)
  {
    // if the given collection does not contain elements
    // we remove all the elements from our storage
    if (c.size() == 0)
      {
        this.clear();
        return true;
      }
    E [] snapshot = this.data;
    E [] storage = (E[]) new Object[this.data.length];
    int length = 0;
    for (E element : snapshot)
      {
        if (c.contains(element))
          storage[length++] = element;
      }
    // means we retained all the elements previously in our storage
    // we are running already slow here, but at least we avoid copying
    // another array and changing the internal storage
    if (length == snapshot.length)
      return false;
    E[] newData = (E[]) new Object[length];
    System.arraycopy(storage, 0, newData, 0, length);
    this.data = newData;
    return true;
  }
  /**
   * Removes all elements from this List
   */
  public synchronized void clear()
  {
    data = (E[]) new Object[0];
  }
  /**
   * Add each element in the supplied Collection to this List. It is undefined
   * what happens if you modify the list while this is taking place; for
   * example, if the collection contains this list. c can contain objects of any
   * type, as well as null values.
   *
   * @param c
   *          a Collection containing elements to be added to this List
   * @return true if the list was modified, in other words c is not empty
   * @throws NullPointerException
   *           if c is null
   */
  public synchronized boolean addAll(Collection< ? extends E> c)
  {
    return addAll(data.length, c);
  }
  /**
   * Add all elements in the supplied collection, inserting them beginning at
   * the specified index. c can contain objects of any type, as well as null
   * values.
   *
   * @param index
   *          the index at which the elements will be inserted
   * @param c
   *          the Collection containing the elements to be inserted
   * @throws IndexOutOfBoundsException
   *           if index < 0 || index > 0
   * @throws NullPointerException
   *           if c is null
   */
  public synchronized boolean addAll(int index, Collection< ? extends E> c)
  {
    if (index < 0 || index > this.size())
      throw new IndexOutOfBoundsException("index = " +  index);
    int csize = c.size();
    if (csize == 0)
      return false;
    E[] data = this.data;
    Iterator extends E> itr = c.iterator();
    E[] newData = (E[]) new Object[data.length + csize];
    // avoid this call at all if we were asked to put the elements at the
    // beginning of our storage
    if (index != 0)
      System.arraycopy(data, 0, newData, 0, index);
    int itemsLeft = index;
    for (E value : c)
      newData[index++] = value;
    // now copy the remaining elements
    System.arraycopy(data, itemsLeft, newData, 0, data.length - itemsLeft);
    this.data = newData;
    return true;
  }
  /**
   * Adds an element if the list does not contains it already.
   *
   * @param val the element to add to the list.
   * @return true if the element was added, false otherwise.
   */
  public synchronized boolean addIfAbsent(E val)
  {
    if (contains(val))
      return false;
    add(val);
    return true;
  }
  /**
   * Adds all the element from the given collection that are not already
   * in this list.
   *
   * @param c the Collection containing the elements to be inserted
   * @return true the list internal storage changed as a result of this
   * operation, false otherwise.
   */
  public synchronized int addAllAbsent(Collection extends E> c)
  {
    int size = c.size();
    if (size == 0)
      return 0;
    E [] snapshot = this.data;
    E [] storage = (E[]) new Object[size];
    size = 0;
    for (E val : c)
      {
        if (!this.contains(val))
          storage[size++] = val;
      }
    if (size == 0)
      return 0;
    // append storage to data
    E [] newData = (E[]) new Object[snapshot.length + size];
    System.arraycopy(snapshot, 0, newData, 0, snapshot.length);
    System.arraycopy(storage, 0, newData, snapshot.length, size);
    this.data = newData;
    return size;
  }
  public String toString()
  {
    return Arrays.toString(this.data);
  }
  public boolean equals(Object o)
  {
    if (o == null)
      return false;
    if (this == o)
      return true;
    // let's see if 'o' is a list, if so, we need to compare the elements
    // as returned by the iterator
    if (o instanceof List)
      {
        List> source = (List>) o;
        if (source.size() != this.size())
          return false;
        Iterator> sourceIterator = source.iterator();
        for (E element : this)
          {
            if (!element.equals(sourceIterator.next()))
              return false;
          }
        return true;
      }
    return false;
  }
  public int hashCode()
  {
    // see http://java.sun.com/6/docs/api/java/util/List.html#hashcode()
    int hashcode = 1;
    for (E element : this)
      {
        hashcode = 31 * hashcode + (element == null ? 0 : element.hashCode());
      }
    return hashcode;
  }
  /**
   * Return an Iterator containing the elements of this list.
   * The Iterator uses a snapshot of the state of the internal storage
   * at the moment this method is called and does not support
   * update operations, so no synchronization is needed to traverse the
   * iterator.
   *
   * @return an Iterator containing the elements of this list in sequence.
   */
  public Iterator* * This implementation returns a subclass of AbstractList. It stores, in * private fields, the offset and size of the sublist, and the expected * modCount of the backing list. If the backing list implements RandomAccess, * the sublist will also. *
   *
   * The subclass's set(int, Object), get(int),
   * add(int, Object), remove(int),
   * addAll(int, Collection) and
   * removeRange(int, int) methods all delegate to the
   * corresponding methods on the backing abstract list, after
   * bounds-checking the index and adjusting for the offset. The
   * addAll(Collection c) method merely returns addAll(size, c).
   * The listIterator(int) method returns a "wrapper object"
   * over a list iterator on the backing list, which is created with the
   * corresponding method on the backing list. The iterator()
   * method merely returns listIterator(), and the size() method
   * merely returns the subclass's size field.
   * 
   *
   * All methods first check to see if the actual modCount of the backing
   * list is equal to its expected value, and throw a
   * ConcurrentModificationException if it is not.
   *
   * @param fromIndex the index that the returned list should start from
   *        (inclusive)
   * @param toIndex the index that the returned list should go to (exclusive)
   * @return a List backed by a subsection of this list
   * @throws IndexOutOfBoundsException if fromIndex < 0
   *         || toIndex > size()
   * @throws IndexOutOfBoundsException if fromIndex > toIndex
   * @see ConcurrentModificationException
   * @see RandomAccess
   */
  public synchronized Listnext()
         *
         * @return The index of the next element.
         */
        public int nextIndex()
        {
          return i.nextIndex() - offset;
        }
        /**
         * Returns the index of the previous element in the
         * list, which will be retrieved by previous()
         *
         * @return The index of the previous element.
         */
        public int previousIndex()
        {
          return i.previousIndex() - offset;
        }
        /**
         * Removes the last object retrieved by next()
         * from the list, if the list supports object removal.
         *
         * @throws IllegalStateException if the iterator is positioned
         *         before the start of the list or the last object has already
         *         been removed.
         * @throws UnsupportedOperationException if the list does
         *         not support removing elements.
         */
        public void remove()
        {
          throw new UnsupportedOperationException("Modification not supported " +
              "on CopyOnWriteArrayList iterators");
        }
        /**
         * Replaces the last object retrieved by next()
         * or previous with o, if the list supports object
         * replacement and an add or remove operation has not already
         * been performed.
         *
         * @throws IllegalStateException if the iterator is positioned
         *         before the start of the list or the last object has already
         *         been removed.
         * @throws UnsupportedOperationException if the list doesn't support
         *         the addition or removal of elements.
         * @throws ClassCastException if the type of o is not a valid type
         *         for this list.
         * @throws IllegalArgumentException if something else related to o
         *         prevents its addition.
         * @throws ConcurrentModificationException if the list
         *         has been modified elsewhere.
         */
        public void set(E o)
        {
          throw new UnsupportedOperationException("Modification not supported " +
              "on CopyOnWriteArrayList iterators");
        }
        /**
         * Adds the supplied object before the element that would be returned
         * by a call to next(), if the list supports addition.
         *
         * @param o The object to add to the list.
         * @throws UnsupportedOperationException if the list doesn't support
         *         the addition of new elements.
         * @throws ClassCastException if the type of o is not a valid type
         *         for this list.
         * @throws IllegalArgumentException if something else related to o
         *         prevents its addition.
         * @throws ConcurrentModificationException if the list
         *         has been modified elsewhere.
         */
        public void add(E o)
        {
          throw new UnsupportedOperationException("Modification not supported " +
              "on CopyOnWriteArrayList iterators");
        }
      };
    }
  } // class SubList
  /**
   * This class is a RandomAccess version of SubList, as required by
   * {@link AbstractList#subList(int, int)}.
   *
   * @author Eric Blake (ebb9@email.byu.edu)
   */
  private static final class RandomAccessSubList