ArrayList source code analysis of Java class set framework
ArrayList
Array-based implementation is essentially a variable-length array referenced by an object, which can dynamically increase or decrease its size.
It is not thread-safe and can only be used in a single-threaded environment. In a multi-threaded environment, you can use the Collection. synchronizedList (List l) function to return a thread-safe ArrayList class. You can also use
CopyOnWriteArrayList class
The following describes the Java Implementation of ArrayList. The source is JDK1.8.0 _ 25/src.zip.
Public class ArrayList
Extends actlist
Implements List
, RandomAccess, Cloneable, java. io. serializable {// implements the RandomAccess interface, supports fast Random Access // implements the Cloneable interface, can be cloned // implements the Serializable interface, and supports serialization of private static final long serialVersionUID = 8683452584252892189l; // sequence version private static final int DEFAULT_CAPACITY = 10; // default initial capacity private static final Object [] EMPTY_ELEMENTDATA = {}; // empty array private static final Object [] DEFAULTCAPACITY_EMPTY_ELEMENTDATA ={}; // default empty array transient Object [] elementData; // private int size will not be serialized; // ArrayList actual element capacity // constructor 1 --- constructor with capacity size public ArrayList (int initialCapacity) {if (initialCapacity> 0) {this. elementData = new Object [initialCapacity]; // specify the size array} else if (initialCapacity = 0) {this. elementData = EMPTY_ELEMENTDATA;} else {throw new IllegalArgumentException ("Illegal Capacity:" + initialCapacity) ;}// constructor 2 --- no parameter constructor, no large hours specified, the public ArrayList () {this. elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;} // constructor 3 --- constructs a list containing the specified collection elements. These elements are sorted by the collection iterator and returned by their public ArrayList (Collection
C) {elementData = c. toArray (); if (size = elementData. length )! = 0) {// c. toArray might (incorrectly) not return Object [] (see 6260652) // http://bugs.java.com/bugdatabase/view_bug.do? Bug_id = 6260652 check the bug library if (elementData. getClass ()! = Object []. class) elementData = Arrays. copyOf (elementData, size, Object []. class);} else {// replace with empty array. this. elementData = EMPTY_ELEMENTDATA ;}// set the current capacity to the actual capacity public void trimToSize () {modCount ++; // fast-fail mechanism, concurrentModificationException will be thrown if the set is modified during access if (size <elementData. length) {elementData = (size = 0 )? EMPTY_ELEMENTDATA: Arrays. copyOf (elementData, size) ;}// increase the capacity to minCapacity public void ensureCapacity (int minCapacity) {int minExpand = (elementData! = Defacapcapacity_empty_elementdata )? 0: DEFAULT_CAPACITY; if (minCapacity> minExpand) {minute (minCapacity) ;}} private void ensureCapacityInternal (int minCapacity) {if (elementData = minute) {minCapacity = Math. max (DEFAULT_CAPACITY, minCapacity) ;}ensureexplicitcapacity (minCapacity) ;}private void evaluate (int minCapacity) {modCount ++; // overflow-conscious code if (minC) Apacity-elementData. length> 0) grow (minCapacity);} private static final int MAX_ARRAY_SIZE = Integer. MAX_VALUE-8; // maximum allocable capacity // each time the memory is re-allocated, the new capacity is 1.5 times the old capacity. // However, if the allocated capacity exceeds the available memory range, an Integer is allocated. MAX_VALUE size, compare the size of the capacity to be allocated and the maximum allocable capacity, if it is greater than the allocated Integer. MAX_VALUE. If the value is smaller than, the maximum capacity is allocated. private void grow (int minCapacity) {// overflow-conscious code int oldCapacity = elementData. length; int newCapacity = oldCapacity + (oldCapacity> 1); // set new capacity = raw capacity * 1.5 if (newCapacity-minCapacity <0) // the added capacity is not newCapacity = minCapacity; if (newCapacity-MAX_ARRAY_SIZE> 0) newCapacity = hugeCapacity (minCapacity); // minCapacity is usually close to size, so this is a win: elementData = Arrays. copyOf (elementData, newCapacity);} private static int hugeCapacity (int minCapacity) {if (minCapacity <0) // overflow throw new OutOfMemoryEr Ror (); return (minCapacity> MAX_ARRAY_SIZE )? Integer. MAX_VALUE: MAX_ARRAY_SIZE;} public int size () {return size;} // whether it is null public boolean isEmpty () {return size = 0 ;} // whether the specified Element o public boolean contains (Object o) {return indexOf (o)> = 0;} // return the specified element position. If no-1 is returned, the searched element can be null 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;} // returns the last occurrence location. If-1 public int lastIndexOf (Object o) is not returned) {if (o = null) {for (int I = size-1; I> = 0; I --) // search for if (elementData [I] = null) return I;} else {for (int I = size-1; I> = 0; I --) from the back --) if (o. equals (elementData [I]) return I;} return-1;} // clone function public Object clone () {try {ArrayList
V = (ArrayList
) Super. clone (); 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 (e );}} public Object [] toArray () {return Arrays. copyOf (elementData, size) ;}@ SuppressWarnings ("unchecked") public
T [] toArray (T [] a) {if (. length <size) // Make a new array of a's runtime type, but my contents: return (T []) Arrays. copyOf (elementData, size,. getClass (); System. arraycopy (elementData, 0, a, 0, size); if (. length> size) a [size] = null; return a;} // Positional Access Operations @ SuppressWarnings ("unchecked") E elementData (int index) {return (E) elementData [index];}/*** Returns the elem Ent at the specified position in this list. ** @ param index of the element to return * @ return the element at the specified position in this list * @ throws IndexOutOfBoundsException {@ inheritDoc} */public E get (int index) {rangeCheck (index); return elementData (index);} public E set (int index, E element) {rangeCheck (index); E oldValue = elementData (index ); elementData [index] = element; r Eturn oldValue;} public boolean add (E e) {ensureCapacityInternal (size + 1); // Increments modCount !! ElementData [size ++] = e; return true;} // Add an element at the specified position. The original position element does not disappear, but is moved back, move the current element and all subsequent elements to the right. Public void add (int index, E element) {rangeCheckForAdd (index); ensureCapacityInternal (size + 1); // Increments modCount !! // Copy the elements in elementData starting from the Index and with the length of size-index to the System in the new elementData array starting from the subscript index + 1. arraycopy (elementData, index, elementData, index + 1, size-index); elementData [index] = element; size ++;} // removes elements at a specified position, after this position, all elements are moved forward to one 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; // clear to let GC do its work return oldValue ;} // remove the specified element that appears for the first time in the list. if no such element exists, false 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;} private void fastRemove (int index) {modCount ++; int numMoved = size-index-1; if (numMoved> 0) System. arraycopy (elementData, index + 1, elementData, index, numMoved); elementData [-- size] = null; // clear to let GC do its work} public void clear () {modCount ++; // clear to let GC do its work for (int I = 0; I <size; I ++) elementData [I] = null; size = 0;} public boolean addAll (Collection
C) {Object [] a = c. toArray (); int numNew =. length; ensureCapacityInternal (size + numNew); // Increments modCount System. arraycopy (a, 0, elementData, size, numNew); size + = numNew; return numNew! = 0;} public boolean addAll (int index, Collection
C) {rangeCheckForAdd (index); Object [] a = c. toArray (); int numNew =. length; ensureCapacityInternal (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;} protected void removeRange (int fromIndex, int toIndex) {modCount ++; int numMoved = size-toIndex; System. arraycopy (elementData, toIndex, elementData, fromIndex, numMoved); // clear to let GC do its work int newSize = size-(toIndex-fromIndex); for (int I = newSize; I <size; I ++) {elementData [I] = null;} size = newSize ;}
Constructor:
ArrayList has three constructor methods. The parameter can specify the capacity size and can be empty (an empty array with the default size of 10 will be constructed at this time ), you can also Initialize an array by the elements in set c.
Capacity growth method:
For more information about the capacity growth method of ArrayList, see grow (). ArrayList indirectly calls this method to ensure capacity each time an element is added. The maximum allocable capacity is MAX_ARRAY_SIZE = Integer. MAX_VALUE-8.
However, the actual maximum allocated capacity may be Integer. MAX_VALUE.
When adding an element, if the current capacity is insufficient to accommodate the element, set the new capacity to about 1.5 times of the old capacity. The previous version is
newCapacity = (oldCapacity * 3)/2 + 1;
JDK1.8 adopts the following methods:
newCapacity = oldCapacity + (oldCapacity >> 1);
Shift operations are faster than multiplication and division operations.
If the new capacity after expansion is still insufficient, set the new capacity to the input parameter (minCapacity ). If the new capacity ratio after expansion is MAX_ARRAY_SIZE = Integer. if the value of MAX_VALUE-8 is large, the capacity is set to Integer regardless of whether the value is full or not. MAX_VALUE, Which is previously mentioned to allow the maximum allocation capacity to be MAX_ARRAY_SIZE, but the actual maximum allocation capacity may be Integer. MAX_VALUE. Of course, the minimum allocated capacity is the default capacity of 10, even if the specified allocation capacity is less than 10, the capacity is also allocated 10,
Note:
When searching for elements, you can look for the null element index. From the source code, you can see that when searching for elements, it is to distinguish between null and non-null.
It must be noted that after resizing, It is very time-consuming to copy the original elements to a new array. Therefore, we recommend that you use ArrayList only when you know the number of elements in advance, otherwise, we recommend that you use consumer list.
ArrayList is implemented based on arrays. Therefore, you can use subscript indexes to directly search for elements at a specified position. Therefore, the search efficiency is high. However, during the process of inserting and deleting elements, a large number of elements need to be moved, which is very inefficient.