[Java Collection source code analysis] ArrayList source code analysis

Source: Internet
Author: User
Tags addall

Reprinted please indicate the source: http://blog.csdn.net/ns_code/article/details/35568011


ArrayList Overview

ArrayList is implemented based on arrays. It is a dynamic array with its capacity Automatically increasing. It is similar to dynamic memory application in C language and dynamic memory growth.

ArrayList is NOT thread-safe and can only be used in a single-threaded environment. Collections can be used in a multi-threaded environment. the synchronizedList (List l) function returns a thread-safe ArrayList class. You can also use the CopyOnWriteArrayList class under the concurrent package.

ArrayList implements the Serializable interface. Therefore, it supports serialization and implements the RandomAccess interface through serialization and transmission. It supports fast random access. In fact, it uses subscript numbers for fast access and implements the Cloneable interface, can be cloned.


ArrayList source code analysis

The source code of ArrayList is as follows (detailed notes are added ):

Package java. util; public class ArrayList <E> extends actlist <E> implements List <E>, RandomAccess, Cloneable, java. io. serializable {// sequence version private static final long serialVersionUID = 8683452584252892189l; // ArrayList is implemented based on this array and uses this array to save private transient Object [] elementData; // The actual amount of data in the ArrayList is private int size; // ArrayList contains a constructor with a capacity. Public ArrayList (int initialCapacity) {super (); if (initialCapacity <0) throw new IllegalArgumentException ("Illegal Capacity:" + initialCapacity); // create an array this. elementData = new Object [initialCapacity];} // ArrayList No parameter constructor. The default capacity is 10. Public ArrayList () {this (10);} // create an ArrayList public ArrayList (collection <? Extends E> c) {elementData = c. toArray (); size = elementData. length; if (elementData. getClass ()! = Object []. class) elementData = Arrays. copyOf (elementData, size, Object []. class) ;}// set the current capacity value to the actual number of elements public void trimToSize () {modCount ++; int oldCapacity = elementData. length; if (size <oldCapacity) {elementData = Arrays. copyOf (elementData, size) ;}// determine the ArrarList capacity. // If the ArrayList capacity is insufficient to accommodate all the current elements, set the new capacity = "(original capacity x3)/2 + 1" public void ensureCapacity (int minCapacity) {// modify the number of Statistics + 1. This variable is mainly used to implement the fail-fast mechanism modCount ++; int oldCapacity = elementData. length; // if the current capacity is insufficient to accommodate the current number of elements, set the new capacity to "(original capacity x3)/2 + 1" if (minCapacity> oldCapacity) {Object oldData [] = elementData; int newCapacity = (oldCapacity * 3)/2 + 1; // if not, set minCapacity to the current capacity if (newCapacity <minCapacit Y) newCapacity = minCapacity; elementData = Arrays. copyOf (elementData, newCapacity) ;}// add the element e public boolean add (E e) {// determine the size of the ArrayList. ensureCapacity (size + 1 ); // Increments modCount !! // Add e to the ArrayList. elementData [size ++] = e; return true;} // return the actual size of the ArrayList public int size () {return size ;} // whether ArrayList contains Object (o) public boolean contains (Object o) {return indexOf (o)> = 0 ;}// whether the ArrayList is null public boolean isEmpty () is returned () {return size = 0;} // forward lookup, returns the index value of the element 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;} // reverse lookup, returns the element's index value public int lastIndexOf (Object o) {if (o = null) {for (int I = size-1; I> = 0; I --) if (elementData [I] = null) return I ;} else {for (int I = size-1; I> = 0; I --) if (o. equals (elementData [I]) return I;} return-1;} // reverse lookup (start from the end of the array), return element (o) public int lastIndexOf (Object o) {if (O = null) {for (int I = size-1; I> = 0; I --) if (elementData [I] = null) return I ;} else {for (int I = size-1; I> = 0; I --) if (o. equals (elementData [I]) return I;} return-1;} // returns the array of objects in ArrayList public Object [] toArray () {return Arrays. copyOf (elementData, size);} // returns an array composed of ArrayList elements public <T> T [] toArray (T []) {// if the size of array a is <Number of ArrayList elements; // A new T [] array is created. The array size is "Number of ArrayList elements" and RrayList "all copies to the new array if (. length <size) return (T []) Arrays. copyOf (elementData, size,. getClass (); // if the size of array a is greater than or equal to the number of elements in the ArrayList, all the elements in the ArrayList are copied to array. System. arraycopy (elementData, 0, a, 0, size); if (. length> size) a [size] = null; return a;} // obtain the element value at the index position public E get (int index) {RangeCheck (index); return (E) elementData [index];} // set the index position to element public E set (int index, E element) {RangeCheck (index); E oldValue = (E) elementData [index]; elementData [index] = element; return oldValue;} // add e to the ArrayList public boolean add (E e ){ EnsureCapacity (size + 1); // Increments modCount !! ElementData [size ++] = e; return true ;}// add e to the specified position of ArrayList public void add (int index, E element) {if (index> size | index <0) throw new IndexOutOfBoundsException ("Index:" + index + ", Size:" + size); ensureCapacity (size + 1 ); // Increments modCount !! System. arraycopy (elementData, index, elementData, index + 1, size-index); elementData [index] = element; size ++ ;} // Delete the public E remove (int index) {RangeCheck (index); modCount ++; E oldValue = (E) elementData [index] element at the specified position in the ArrayList; 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;} // Delete the specified 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 ;}// you can quickly delete the private void fastRemove (int index ){ ModCount ++; int numMoved = size-index-1; // starting from "index + 1", replace the previous element with the following element. If (numMoved> 0) System. arraycopy (elementData, index + 1, elementData, index, numMoved); // set the last element to null elementData [-- size] = null; // Let gc do its work} // Delete the public boolean remove (Object o) {if (o = null) {for (int index = 0; index <size; index ++) if (elementData [index] = null) {fastRemove (index); return true ;}} else {// convenience ArrayList, locate "element o ", and return true. For (int index = 0; index <size; index ++) if (o. equals (elementData [index]) {fastRemove (index); return true ;}return false ;}// clear ArrayList and set all elements to null public void clear () {modCount ++; for (int I = 0; I <size; I ++) elementData [I] = null; size = 0 ;} // append the set c to the public boolean addAll (Collection <? Extends E> c) {Object [] a = c. toArray (); int numNew =. length; ensureCapacity (size + numNew); // Increments modCount System. arraycopy (a, 0, elementData, size, numNew); size + = numNew; return numNew! = 0;} // Add the set c to ArrayList public boolean addAll (int index, Collection <? Extends E> c) {if (index> size | index <0) throw new IndexOutOfBoundsException ("Index:" + index + ", Size:" + size ); object [] a = c. toArray (); int numNew =. length; ensureCapacity (size + numNew); // Increments modCount int numMoved = size-index; if (numMoved> 0) System. arraycopy (elementData, index, elementData, index + numNew, numMoved); System. arraycopy (a, 0, elementData, index, numNew ); Size + = numNew; return numNew! = 0;} // delete all elements from fromIndex to toIndex. Protected void removeRange (int fromIndex, int toIndex) {modCount ++; int numMoved = size-toIndex; System. arraycopy (elementData, toIndex, elementData, fromIndex, numMoved); // Let gc do its work int newSize = size-(toIndex-fromIndex); while (size! = NewSize) elementData [-- size] = null;} private void RangeCheck (int index) {if (index> = size) throw new IndexOutOfBoundsException ("Index:" + index + ", size: "+ size);} // clone function public Object clone () {try {ArrayList <E> v = (ArrayList <E>) super. clone (); // copy all the elements of the current ArrayList to v. elementData = Arrays. copyOf (elementData, size); v. modCount = 0; return v;} catch (CloneNotSupportedException e ){// This shouldn't happen, since we are Cloneable throw new InternalError () ;}// java. io. serializable write function // write the "capacity, all element values" of ArrayList to the 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 "array capacity" s. writeInt (elementData. length); // write "every element of the array" for (int I = 0; I <size; I ++) s. writeObject (elementData [I]); if (modCount! = ExpectedModCount) {throw new ConcurrentModificationException () ;}// java. io. serializable READ function: reads the "capacity" of the ArrayList according to the write method, and then reads the "All element values" from the private void readObject (java. io. objectInputStream s) throws java. io. IOException, ClassNotFoundException {// Read in size, and any hidden stuff s. defaultReadObject (); // read the "capacity" int arrayLength = s of the ArrayList from the input stream. readInt (); Object [] a = elementData = new Object [arrayLength]; // read "All element values" from the input stream for (int I = 0; I <size; I ++) a [I] = s. readObject ();}}

Summary

The source code of ArrayList provides several important summaries:

1. Pay attention to the three different constructor methods. The capacity of the ArrayList constructed by the non-argument constructor is 10 by default. The constructor with the Collection parameter converts the Collection into an array and assigns it to the Implementation array elementData of the ArrayList.

2. ensureCapacity. Each time an element (either one or a group) is added to ArrayList, this method must be called to ensure sufficient capacity. When the capacity is insufficient to accommodate the current number of elements, set the new capacity to 1.5 times of the old capacity and 1. If the new capacity is not enough, the new capacity is directly set to the input parameter (that is, the required capacity), and then the Arrays is used. the copyof () method copies the elements to the new array (see the 3rd points below ). It can be seen that when the capacity is insufficient, each time an element is added, the original element must be copied to a new array, which is very time consuming, therefore, we recommend that you use ArrayList only when you can determine the number of elements in advance. Otherwise, we recommend that you use limit list.

3. Arrays. copyof () and System. arraycopy () methods are largely called in the implementation of ArrayList. We need to have a deep understanding of the implementation of these two methods.

First, let's look at the Arrays. copyof () method. It has many overload methods, but the implementation idea is the same. Let's look at the source code of the generic version:

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

Obviously, another copyof method is called. This method has three parameters. The last parameter specifies the type of data to be converted. The source code is 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;    }

It is obvious that this method actually creates an array with the length of newlength in it and calls System. the arraycopy () method copies the elements in the original array to the new array.

The following describes the System. arraycopy () method. This method is marked as native and calls the C/C ++ code of the system. It cannot be seen in JDK, but its source code can be seen in openJDK. This function actually calls the memmove () function in C language. Therefore, it ensures that elements in the same number of groups are correctly copied and moved, which is much more efficient than the general replication method, it is suitable for batch processing arrays. Java strongly recommends this method when copying a large number of array elements to achieve higher efficiency.

4. Note that the two methods of ArrayList are converted to the toArray method of static arrays.

First, the Object [] toArray () method. This method may throw java. lang. classCastException: If you directly use the downward transformation method to convert the entire ArrayList set to an Array of the specified type, this exception is thrown. If the Array is converted to an Array, no downward transformation is performed, however, if each element is transformed downward, this exception is not thrown. Obviously, the elements in the array are transformed downward, Which is inefficient and inconvenient.

Second, <T> T [] toArray (T [] a) method. This method can directly transform the Array obtained by the ArrayList conversion to the whole (the transformation is actually implemented in the source code of this method). It can be seen from the source code of this method, when the size of parameter a is insufficient, Arrays is called internally. copyOf method. This method internally creates a new array to return results. Therefore, the common form of this method is as follows:

public static Integer[] vectorToArray2(ArrayList<Integer> v) {      Integer[] newText = (Integer[])v.toArray(new Integer[0]);      return newText;  }  

5. ArrayList is implemented based on arrays. You can use subscript indexes to directly find the elements at the specified position. Therefore, the search efficiency is high. However, each time an element is inserted or deleted, a large number of elements need to be moved, it is inefficient to insert and delete elements.

6. In the method of searching for the index value of a given element, the source code classifies the value of this element into null and not null. The ArrayList allows the element to be null.

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.