"Java Source code Analysis" ArrayList source analysis

Source: Internet
Author: User
Tags concurrentmodificationexception

Definition of Class

public class ArrayList<E> extends AbstractList<E>    implements List<E>, RandomAccess, Cloneable, java.io.Serializable {}
    1. The implementation class of the list interface, the subclass of Abstractlist, supports random access, so the underlying implementation of the data structure is an array
    2. All list operations are implemented, allowing all types of elements, including null
    3. Provides an interface for calculating the size of an array, which can be seen as a vector, except that the vector is thread-safe and ArrayList is not
    4. Because the underlying implementation data structure is an array, the Get set iterator traversal, and the size is judged to be constant time. Other operations are linear time complexity, and the constant factor is smaller than linkedlist, so the efficiency is slightly higher
    5. Contains a capacity capacity instance, indicating the size of the capacity, as the data is added, the instance will be self-increasing, self-increasing
    6. Non-thread safe, so if you need to handle thread safety problems in a multithreaded environment, you can use Collections.synchronizedList methods List list = Collections.synchronizedList(new ArrayList(...)); to wrap them, and it is best to consider whether you need to do multi-threaded processing to avoid errors when declaring variables.
    7. ConcurrentModificationExceptionException, if an instance of ArrayList is traversed using an iterator iterator, if a remove or add operation is made that does not use this iterator, then the concurrent modified exception is thrown directly. This exception occurs even if it is single-threaded, and the common scenario is when you use an iterator to iterate over the ArrayList object while you are modifying it.
    8. For the 7 phenomenon is also called fail-fast , the behavior can only try to detect the concurrency exception, but not the absolute thread safety, so when programming do not because the exception is not thrown to feel that it is thread-safe

constructor function
There are three types, the default construct (the size of the default constructed LISTD is 10), the construction of a size is passed, and the construction of a collection object is passed.

public ArrayList(int initialCapacity) {    super();    if (initialCapacity < 0)        throw new IllegalArgumentException("Illegal Capacity: "+                                           initialCapacity);    this.elementData = new Object[initialCapacity];}public ArrayList() {    this(10);}public ArrayList(Collection<? extends E> c) {    elementData = c.toArray();    size = elementData.length;    // c.toArray might (incorrectly) not return Object[] (see 6260652)    if (elementData.getClass() != Object[].class)        elementData = Arrays.copyOf(elementData, size, Object[].class);}

Expansion mode

  private transient object[] elementdata;//object array, an array container that actually holds data, default initial 10 objectprivate int size; Number of objects actually stored private static final int max_array_size = integer.max_value-8; Maximum capacity; Because some virtual opportunities store some information in the array header, subtract 8 bytes of private void grow (int mincapacity) {//overflow-conscious code int Oldcapa    City = Elementdata.length;    int newcapacity = oldcapacity + (oldcapacity >> 1);    if (newcapacity-mincapacity < 0) newcapacity = mincapacity;    if (newcapacity-max_array_size > 0) newcapacity = hugecapacity (mincapacity); Mincapacity is usually close to size, so the is a win:elementdata = arrays.copyof (Elementdata, newcapacity);} 

Expansion occurs when an element is added and the existing array is not placed, and the expansion function is called. Since there is a copy process in the process of expansion, and the copy is a copy of the entire collection, it is still very influential in performance, so it is best to start by estimating how much capacity will be used, to avoid the use of the frequent expansion of the process. Expansion of the idea is the default expansion of the original 1.5 times times, if the specified value mincapacity than the original capacity of 1.5 times times larger, then the specified value of the expansion; if the specified value mincapacity than the threshold value max_array_size, then the following policy determines the size of the expansion final (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;, there is a certain risk of oom

Reduced capacity to reduce storage space for one ArrayList instance

public void trimToSize() {    modCount++;    int oldCapacity = elementData.length;    if (size < oldCapacity) {        elementData = Arrays.copyOf(elementData, size);    }}

From the following side, the ArrayList is allowed to be stored in an empty object.

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

Joins the bridge of the collection class collection and the linear table array class, which copies the objects stored in the collection to an array of objects to return

public Object[] toArray() {    return Arrays.copyOf(elementData, size);}

The method also has another polymorphic implementation that returns an array of the specified type based on the run-time type

public <T> T[] toArray(T[] a) { ... }

Add an element to a collection

public void add(int index, E element) {    rangeCheckForAdd(index);    ensureCapacityInternal(size + 1);  // Increments modCount!!    System.arraycopy(elementData, index, elementData, index + 1,                     size - index);    elementData[index] = element;    size++;}

This is added to the specified location, so it is more troublesome and requires a copy to move. There is also an add operation is added directly to the tail, public boolean add(E e) { ... } only need to do a single assignment to

Deletes the element at the specified position

public E remove(int index) {    rangeCheck(index);    modCount++;    E oldValue = elementData(index);    int numMoved = size - index - 1;    if (numMoved > 0)        System.arraycopy(elementData, index+1, elementData, index,                         numMoved);    elementData[--size] = null; // Let gc do its work    return oldValue;}

From the code it is also relatively understood, delete the specified position element, and then specify the position after the element is moved forward, which is an array copy process. But the last point to be aware of is to empty the last vacated position, as mentioned in effective Java, which is to eliminate outdated references in a timely manner . For some custom array classes if the object is moved, but the pointer is not set to NULL, the strong reference will persist, causing a memory leak.

Another delete operation is to delete the specified object

public boolean remove(Object o) {    if (o == null) {        for (int index = 0; index < size; index++)            if (elementData[index] == null) {                fastRemove(index);                return true;            }    } else {        for (int index = 0; index < size; index++)            if (o.equals(elementData[index])) {                fastRemove(index);                return true;            }    }    return false;}

It uses a private delete operation, which is fastRemove(index) characterized by not checking the boundary and not returning the deleted value, after all, it is internal call, already can ensure that the boundary is correct.

Clear operation

public void clear() {    modCount++;    // Let gc do its work    for (int i = 0; i < size; i++)        elementData[i] = null;    size = 0;}

Compare directly, loop empty, and then give the object's cleanup work to the GC, note that clear just empties the contents, the collection container or the

Remove some elements from a collection

public boolean removeAll(Collection<?> c) {    return batchRemove(c, false);}

The function is to remove all elements that are in C

Keep some elements of the collection

public boolean retainAll(Collection<?> c) {    return batchRemove(c, true);}

The function is to keep all elements that are in C intact, not all elements in C are removed
Comparing these two methods can be seen, the actual work is done by the private boolean batchRemove(Collection<?> c, boolean complement) {} completion of the second argument is true when the time represents a reserved element, otherwise the deletion.

State saving and recovery of collection data

private void writeObject(java.io.ObjectOutputStream s)    throws java.io.IOException{    // Write out element count, and any hidden stuff    int expectedModCount = modCount;    s.defaultWriteObject();    // Write out array length    s.writeInt(elementData.length);    // Write out all elements in the proper order.    for (int i=0; i<size; i++)        s.writeObject(elementData[i]);    if (modCount != expectedModCount) {        throw new ConcurrentModificationException();    }}

Recover, take data out of the stream

private void readObject(java.io.ObjectInputStream s)    throws java.io.IOException, ClassNotFoundException {    // Read in size, and any hidden stuff    s.defaultReadObject();    // Read in array length and allocate array    int arrayLength = s.readInt();    Object[] a = elementData = new Object[arrayLength];    // Read in all elements in the proper order.    for (int i=0; i<size; i++)        a[i] = s.readObject();}  

Similar to serialization and deserialization, where state preservation and recovery are paired, the order of preservation and recovery is the same, otherwise it is impossible to get the correct object or collection. Note that it is also not possible to modify the collection when the state is saved, or to throw concurrent modification exceptions

And look at ArrayList's iterator.

Private class Itr implements iterator<e> {int cursor; Index of next element to return int lastret =-1; Index of last element returned;    -1 if no such int expectedmodcount = Modcount;    public Boolean Hasnext () {return cursor! = size;        } @SuppressWarnings ("Unchecked") public E Next () {checkforcomodification ();        int i = cursor;        if (i >= size) throw new nosuchelementexception ();        object[] Elementdata = ArrayList.this.elementData;        if (i >= elementdata.length) throw new Concurrentmodificationexception ();        cursor = i + 1;    Return (E) Elementdata[lastret = i];        } public void Remove () {if (Lastret < 0) throw new IllegalStateException ();        Checkforcomodification ();            try {ArrayList.this.remove (Lastret);            cursor = Lastret;            Lastret =-1;        Expectedmodcount = Modcount; } catch (IndexoutofboundsexCeption ex) {throw new concurrentmodificationexception (); }} final void Checkforcomodification () {if (Modcount! = expectedmodcount) throw new Concurrentmo    Dificationexception (); }}

It is mentioned in the previous iterator that when iterating over an element using the same iterator, it is not possible to modify the structure of the collection (that is, the size, but the content varies in size or is possible, such as add (index, value) or set (index, value), but the add (value), which is modcount++), is willing to save the number of times the current collection has been modified each time an iterator instance is initialized. After each operation of the iterator, it checks to see if the saved value is the same as the Modcount value of the collection, and if different throws the exception directly and ends, this is called fail-fast

Get Child collection Operations

public List<E> subList(int fromIndex, int toIndex) {    subListRangeCheck(fromIndex, toIndex, size);    return new SubList(this, 0, fromIndex, toIndex);}

Returns a subset of the elements from Fromindex to Toindex, excluding Toindex. when Toindex and Fromindex are equal, an empty subset is returned instead of a null pointer.

Note that sublist private class SubList extends AbstractList<E> implements RandomAccess {} is an inner subclass of ArrayList that implements the same method as ArrayList.

Finally, add a copy function that is often called Arrays.copyOf(elementData, newCapacity) andSystem.arraycopy(elementData, index, elementData, index + 1, size - index);

The former eventually calls the arrays copyOf() method

public static <T> T[] copyOf(T[] original, int newLength) {    return (T[]) copyOf(original, newLength, original.getClass());}  

The method is implemented as follows

public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {    T[] copy = ((Object)newType == (Object)Object[].class)        ? (T[]) new Object[newLength]        : (T[]) Array.newInstance(newType.getComponentType(), newLength);    System.arraycopy(original, 0, copy, 0,                     Math.min(original.length, newLength));    return copy;}

The process of implementation is to determine the generic type, and then call the system's copy function to copy the elements from the specified collection to the target collection, which is a new collection of newlength sizes. The function was called during the actual copy process. System.arraycopy()

is a native method

public static native void arraycopy(Object src,  int  srcPos,                                    Object dest, int destPos,                                    int length);

This method copies srcpos+length-1 elements into dest from Destpos to Destpos+length-1. Because it is a native method, it is not visible in the JDK, but you can view the source code in the OPENJDK. The function actually eventually calls the C language's memmove () function, so it can guarantee the correct copying and movement of elements within the same array, which is much more efficient than the general method of replication, and is well suited for batch processing of arrays . Java strongly recommends using this method when copying large numbers of array elements to achieve higher efficiency.

"Java Source code Analysis" ArrayList source analysis

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.