copyonwritearraylist.java
来自「一个很好的微工作流内核」· Java 代码 · 共 1,200 行 · 第 1/3 页
JAVA
1,200 行
/* File: CopyOnWriteArrayList.java Written by Doug Lea. Adapted from JDK1.2 ArrayList.java which carries the following copyright: * Copyright 1997 by Sun Microsystems, Inc., * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A. * All rights reserved. * * This software is the confidential and proprietary information * of Sun Microsystems, Inc. ("Confidential Information"). You * shall not disclose such Confidential Information and shall use * it only in accordance with the terms of the license agreement * you entered into with Sun. History: Date Who What 21Jun1998 dl Create public version 9Oct1999 dl faster equals 29jun2001 dl Serialization methods now private*/package EDU.oswego.cs.dl.util.concurrent;import java.util.*;/** * This class implements a variant of java.util.ArrayList in which * all mutative operations (add, set, and so on) are implemented * by making a fresh copy of the underlying array. * <p> * This is ordinarily too costly, but it becomes attractive when traversal * operations vastly overwhelm mutations, and, especially, * when you cannot or don't want to * synchronize traversals, yet need to preclude interference * among concurrent threads. * The iterator method uses a reference to the * state of the array at the point that the * iterator was created. This array never changes during * the lifetime of the iterator, so interference is impossible. * (The iterator will not traverse elements added or changed * since the iterator was created, but usually this is a desirable * feature.) * <p> * As much code and documentation as possible was shamelessly copied from * java.util.ArrayList (Thanks, Josh!), with the intent of preserving * all semantics of ArrayList except for the copy-on-write * property. * (The java.util * collection code could not be subclassed here since all of the existing * collection classes assume elementwise mutability.) * <p> * Because of the copy-on-write policy, some one-by-one * mutative operations * in the java.util.Arrays and java.util.Collections classes * are so time/space intensive as to never * be worth calling (except perhaps as benchmarks for garbage collectors :-). * <p> * Three methods are supported in addition to * those described in List and ArrayList. The addIfAbsent * and addAllAbsent methods provide Set semantics for add, * and are used in CopyOnWriteArraySet. However, they * can also be used directly from this List version. * The copyIn method (and * a constructor that invokes it) allow * you to copy in an initial array to use. This method can * be useful when you first want to perform many operations * on a plain array, and then make a copy available for * use through the collection API. * <p> * Due to their strict read-only nature, * element-changing operations on iterators * (remove, set, and add) are not supported. These * are the only methods throwing UnsupportedOperationException. * <p> * <p>[<a href="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html"> Introduction to this package. </a>] * @see CopyOnWriteArraySet **/public class CopyOnWriteArrayList implements List, Cloneable, java.io.Serializable { /** * The held array. Directly access only within synchronized * methods */ protected transient Object[] array_; /** * Accessor to the array intended to be called from * within unsynchronized read-only methods **/ protected synchronized Object[] array() { return array_; } /** * Constructs an empty list * */ public CopyOnWriteArrayList() { array_ = new Object[0]; } /** * Constructs an list containing the elements of the specified * Collection, in the order they are returned by the Collection's * iterator. */ public CopyOnWriteArrayList(Collection c) { array_ = new Object[c.size()]; Iterator i = c.iterator(); int size = 0; while (i.hasNext()) array_[size++] = i.next(); } /** * Create a new CopyOnWriteArrayList holding a copy of given array * @param toCopyIn the array. A copy of this array is used as the * internal array. **/ public CopyOnWriteArrayList(Object[] toCopyIn) { copyIn(toCopyIn, 0, toCopyIn.length); } /** * Replace the held array with a copy of the <code>n</code> * elements of the provided array, starting at position <code>first</code>. * To copy an entire array, call with arguments (array, 0, array.length). * @param toCopyIn the array. A copy of the indicated elements of * this array is used as the * internal array. * @param first The index of first position of the array to * start copying from. * @param n the number of elements to copy. This will be the new size of * the list. **/ public synchronized void copyIn(Object[] toCopyIn, int first, int n) { array_ = new Object[n]; System.arraycopy(toCopyIn, first, array_, 0, n); } /** * Returns the number of components in this list. * * @return the number of components in this list. */ public int size() { return array().length; } /** * Tests if this list has no components. * * @return <code>true</code> if this list has no components; * <code>false</code> otherwise. */ public boolean isEmpty() { return size() == 0; } /** * Returns true if this list contains the specified element. * * @param o element whose presence in this List is to be tested. */ public boolean contains(Object elem) { Object[] elementData = array(); int len = elementData.length; return indexOf(elem, elementData, len) >= 0; } /** * Searches for the first occurence of the given argument, testing * for equality using the <code>equals</code> method. * * @param elem an object. * @return the index of the first occurrence of the argument in this * list; returns <code>-1</code> if the object is not found. * @see Object#equals(Object) */ public int indexOf(Object elem) { Object[] elementData = array(); int len = elementData.length; return indexOf(elem, elementData, len); } /** * static version allows repeated call without needed * to grab lock for array each time **/ protected static int indexOf(Object elem, Object[] elementData, int len) { if (elem == null) { for (int i = 0; i < len; i++) if (elementData[i]==null) return i; } else { for (int i = 0; i < len; i++) if (elem.equals(elementData[i])) return i; } return -1; } /** * Searches for the first occurence of the given argument, beginning * the search at <code>index</code>, and testing for equality using * the <code>equals</code> method. * * @param elem an object. * @param index the index to start searching from. * @return the index of the first occurrence of the object argument in * this List at position <code>index</code> or later in the * List; returns <code>-1</code> if the object is not found. * @see Object#equals(Object) */ // needed in order to compile on 1.2b3 public int indexOf(Object elem, int index) { Object[] elementData = array(); int elementCount = elementData.length; if (elem == null) { for (int i = index ; i < elementCount ; i++) if (elementData[i]==null) return i; } else { for (int i = index ; i < elementCount ; i++) if (elem.equals(elementData[i])) return i; } return -1; } /** * Returns the index of the last occurrence of the specified object in * this list. * * @param elem the desired component. * @return the index of the last occurrence of the specified object in * this list; returns -1 if the object is not found. */ public int lastIndexOf(Object elem) { Object[] elementData = array(); int len = elementData.length; return lastIndexOf(elem, elementData, len); } protected static int lastIndexOf(Object elem, Object[] elementData, int len) { if (elem == null) { for (int i = len-1; i >= 0; i--) if (elementData[i]==null) return i; } else { for (int i = len-1; i >= 0; i--) if (elem.equals(elementData[i])) return i; } return -1; } /** * Searches backwards for the specified object, starting from the * specified index, and returns an index to it. * * @param elem the desired component. * @param index the index to start searching from. * @return the index of the last occurrence of the specified object in this * List at position less than index in the List; * -1 if the object is not found. */ public int lastIndexOf(Object elem, int index) { // needed in order to compile on 1.2b3 Object[] elementData = array(); if (elem == null) { for (int i = index; i >= 0; i--) if (elementData[i]==null) return i; } else { for (int i = index; i >= 0; i--) if (elem.equals(elementData[i])) return i; } return -1; } /** * Returns a shallow copy of this list. (The elements themselves * are not copied.) * * @return a clone of this list. */ public Object clone() { try { Object[] elementData = array(); CopyOnWriteArrayList v = (CopyOnWriteArrayList)super.clone(); v.array_ = new Object[elementData.length]; System.arraycopy(elementData, 0, v.array_, 0, elementData.length); return v; } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable throw new InternalError(); } } /** * Returns an array containing all of the elements in this list * in the correct order. */ public Object[] toArray() { Object[] elementData = array(); Object[] result = new Object[elementData.length]; System.arraycopy(elementData, 0, result, 0, elementData.length); return result; } /** * Returns an array containing all of the elements in this list in the * correct order. The runtime type of the returned array is that of the * specified array. If the list fits in the specified array, it is * returned therein. Otherwise, a new array is allocated with the runtime * type of the specified array and the size of this list. * <p> * If the list fits in the specified array with room to spare * (i.e., the array has more elements than the list), * the element in the array immediately following the end of the * collection is set to null. This is useful in determining the length * of the list <em>only</em> if the caller knows that the list * does not contain any null elements. * * @param a the array into which the elements of the list are to * be stored, if it is big enough; otherwise, a new array of the * same runtime type is allocated for this purpose. * @return an array containing the elements of the list. * @exception ArrayStoreException the runtime type of a is not a supertype * of the runtime type of every element in this list. */ public Object[] toArray(Object a[]) { Object[] elementData = array(); if (a.length < elementData.length) a = (Object[]) java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), elementData.length); System.arraycopy(elementData, 0, a, 0, elementData.length); if (a.length > elementData.length) a[elementData.length] = null; return a; } // Positional Access Operations /** * Returns the element at the specified position in this list. * * @param index index of element to return. * @exception IndexOutOfBoundsException index is out of range (index * < 0 || index >= size()). */ public Object get(int index) { Object[] elementData = array(); rangeCheck(index, elementData.length); return elementData[index]; } /** * Replaces the element at the specified position in this list with * the specified element. * * @param index index of element to replace. * @param element element to be stored at the specified position. * @return the element previously at the specified position. * @exception IndexOutOfBoundsException index out of range * (index < 0 || index >= size()). */ public synchronized Object set(int index, Object element) { int len = array_.length; rangeCheck(index, len); Object oldValue = array_[index]; boolean same = (oldValue == element || (element != null && element.equals(oldValue))); if (!same) { Object[] newArray = new Object[len]; System.arraycopy(array_, 0, newArray, 0, len); newArray[index] = element; array_ = newArray; } return oldValue; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?