Turn from: 76760238
Top Notes
The implementation of a variable array of size for the list interface. All optional list operations are implemented and all elements, including NULL, are allowed. In addition to implementing the list interface, this class provides methods to manipulate the size of the array used internally to store the list. (This class is roughly equivalent to the vector class, except that this class is not synchronized.) )
Size, IsEmpty, get, set, iterator, and listiterator operations are all run at a fixed time. The add operation runs at a fixed time of allocation, that is, an O (n) time is required to add n elements. All other operations run in linear time (broadly speaking). This implementation has a low constant factor compared to the constant factor used for LinkedList implementations.
Each ArrayList instance has a capacity. This capacity refers to the size of the array used to store the list elements. It is always at least equal to the size of the list. As you add elements to the ArrayList, their capacity increases automatically. The details of the growth strategy are not specified, as it is not just the addition of elements that can be as simple as allocating fixed-time overhead.
Before adding a large number of elements, an application can use the ensurecapacity operation to increase the capacity of the ArrayList instance. This can reduce the amount of incremental redistribution.
Note that this implementation is not synchronous. If more than one thread accesses a ArrayList instance at the same time, and at least one of the threads modifies the list from the structure, it must remain externally synchronized. (Structural modification refers to any action that adds or removes one or more elements, or explicitly adjusts the size of the underlying array; just setting the value of an element is not a structural modification.) This is typically done by synchronizing the objects that naturally encapsulate the list. If such an object does not exist, you should use the Collections.synchronizedlist method to "wrap" the list. This is best done at the time of creation to prevent accidental access to the list in a different step:
List List = Collections.synchronizedlist (new ArrayList (...));
The iterator returned by the iterator and Listiterator methods of this class is a quick failure: After the iterator is created, the list is modified in any way at any time, unless the list is modified structurally by the Remove or add method of the iterator itself. Iterators will throw concurrentmodificationexception. Therefore, in the face of concurrent modifications, the iterator will soon fail completely, rather than risking arbitrary, indeterminate behavior at some uncertain time in the future.
Note that the fast failure behavior of iterators is not guaranteed because, in general, it is not possible to make any hard guarantees as to whether or not there is a concurrency change in sync. A fast-failing iterator will do its best to throw concurrentmodificationexception. Therefore, it is a mistake to write a program that relies on this exception to improve the correctness of such iterators: The fast failure behavior of iterators should only be used to detect bugs.
This class is a member of the Java Collections Framework.
From the above content can be summed up the following points:
- Bottom : ArrayList is the implementation of the variable size array for the list interface.
- whether NULL is allowed: ArrayList allows null elements.
- time complexity : size, IsEmpty, get, set, iterator, and Listiterator methods all run at a fixed time, with a time complexity of O (1). The Add and remove methods require an O (n) time. This implementation has a low constant factor compared to the constant factor used for LinkedList implementations.
- capacity : The capacity of the ArrayList can grow automatically.
- Sync : ArrayList is not synchronized.
- iterators : The iterator returned by the iterator and Listiterator methods of the ArrayList is fail-fast.
Defined
First look at the definition of ArrayList:
public class Arraylist<e> extends abstractlist<e> implements List<e>,randomaccess,cloneable, Java.io.Serializable
We can learn from the following:
- Arraylist<e>: Description ArrayList supports generics.
- Extends abstractlist<e>: inherited the Abstractlist. Abstractlist provides a backbone implementation of the list interface to minimize the work required to implement llist in a "random Access" data store (such as ArrayList).
- Implements LIST<E>: Implements the List. All optional list operations are implemented.
- Implements Randomaccess: Indicates that the ArrayList supports fast (usually fixed-time) random access. The primary purpose of this interface is to allow a generic algorithm to change its behavior so that it provides good performance when applied to random or contiguous access lists.
- Implements Cloneable: Indicates that it can call the Clone () method to return the Field-for-field copy of the instance.
- Implements Java.io.Serializable: Indicates that the class has serialization capabilities.
Domain
/** * Initialize default capacity. */private static final int default_capacity = 10;/** * Specifies that the ArrayList capacity is 0 o'clock and returns the empty array. */private static final object[] Empty_elementdata = {};/** * When the parameterless constructor method is called, the array is returned. When you first create a ArrayList, the data amount is 0. * It differs from Empty_elementdata: The array is returned by default, while the latter is returned at the user-specified capacity of 0 o'clock. */private static final object[] Defaultcapacity_empty_elementdata = {};/** * Saves the element that is added to the ArrayList. * The capacity of the ArrayList is the length of the array. * When the value is Defaultcapacity_empty_elementdata, the array expands the value default_capacity when the element is first added into ArrayList. * is marked as transient and is not serialized when the object is serialized. */transient object[] Elementdata; Non-private to simplify nested class access/** * ArrayList the actual size (array contains the number of elements). * @serial */private int size;
Construction Method
Next, look at the construction methods provided by ArrayList. ArrayList provides three methods of construction.
- ArrayList (int initialcapacity): Constructs an empty ArrayList with a specified capacity of capacity.
- ArrayList (): Constructs an empty list with an initial capacity of 10.
- ArrayList (collection<? extends e> c): Constructs a list of elements that contain the specified Collection, arranged in the order in which they are returned by the Collection iterator.
ArrayList (int initialcapacity)
/** * Constructs an empty ArrayList that specifies that the capacity is initialized to capacity. * * @param The specified initialization capacity of initialcapacity ArrayList * @throws illegalargumentexception If the specified initialization capacity of ArrayList is negative. */public ArrayList (int initialcapacity) { if (initialcapacity > 0) { this.elementdata = new object[ Initialcapacity]; } else if (initialcapacity = = 0) { this.elementdata = empty_elementdata; } else { throw new Illegalargumentexc Eption ("Illegal capacity:" + initialcapacity);} }
ArrayList ()
/** * Constructs an empty list with an initial capacity of 10. */public ArrayList () { this.elementdata = defaultcapacity_empty_elementdata;}
ArrayList (collection<? extends e> c)
/** * Constructs a list of elements that contain the specified collection, which are arranged in the order in which they are returned by the collection iterator. * * @param c its elements will be placed in this list collection * @throws NullPointerException If the specified collection is null */public ArrayList (collection& lt;? Extends e> c) { elementdata = C.toarray (); if (size = elementdata.length)! = 0) { //C.toarray might (incorrectly) not return object[] (see 6260652) if (ele Mentdata.getclass ()! = object[].class) elementdata = arrays.copyof (elementdata, size, object[].class); } else { //Replace with empty array. This.elementdata = Empty_elementdata; }}
Core approach
ArrayList has the following core methods
Method Name |
Complexity of Time |
Get (int index) |
O (1) |
Add (e E) |
O (1) |
Add (Add (int index, E Element)) |
O (N) |
Remove (int index) |
O (N) |
Set (int index, E Element) |
O (1) |
get (int index)
/** * Returns the element indexed as index in the list * * @param index of the element to be returned * @return the element indexed in the list as index * @throws indexoutofboundsexception if Index exceeds size */public E get (int index) { //cross check Rangecheck (index); Returns the element indexed as index return elementdata (index);} /** * Cross-border check. * Check whether the index given is out of bounds. * Throws a run-time exception if it is out of bounds. * This method does not check whether index is legal. such as whether it is negative. * If the given index index>=size, throw an out-of-bounds exception */private void rangecheck (int index) { if (index >= size) throw new Indexouto Fboundsexception (outofboundsmsg (index));} /** * Returns the element indexed to index */@SuppressWarnings ("unchecked") E elementdata (int index) { return (E) Elementdata[index];}
As you can see from the code, because the ArrayList bottom is an array, its Get method is very simple, first to determine whether there is no bounds, and then directly through the array subscript to get the element. The time complexity of the Get method is O (1).
Add (e E)
/** * Add elements to the end of the list. * * @param e added element * @return True */public boolean add (E e) { //Confirm list capacity, if not enough, capacity plus 1. Note: Add only 1 to ensure that resources are not wasted ensurecapacityinternal (size + 1); Increments modcount!! elementdata[size++] = e; return true;}
expansion-ensurecapacity and other methods
Add ArrayList capacity. * * @param mincapacity desired minimum capacity */public void ensurecapacity (int mincapacity) {//if Elementdata equals defaultcapacity_emp Ty_elementdata, minimum expansion capacity is default_capacity, otherwise 0 int minexpand = (elementdata! = defaultcapacity_empty_elementdata)? 0:default_capacity; If the minimum capacity you want is greater than the minimum expansion capacity, use the desired minimum capacity. if (Mincapacity > Minexpand) {ensureexplicitcapacity (mincapacity); }}/*** array capacity Check, when not enough to expand, only for the class internal use. * * @param mincapacity desired minimum capacity */private void ensurecapacityinternal (int mincapacity) {//if Elementdata = = Defaultcap Acity_empty_elementdata, mincapacity is the maximum value between default_capacity and parameter mincapacity if (elementdata = = Defaultcapacity_ Empty_elementdata) {mincapacity = Math.max (default_capacity, mincapacity); } ensureexplicitcapacity (mincapacity);} /*** array capacity Check, when not enough to expand, only for class internal use * * @param mincapacity want the minimum capacity */private void ensureexplicitcapacity (int mincapacity) {MODC ount++; Ensures the specified minimum capacity > array Buffer current length if (Mincapacity-elementdata.length > 0) Expansion grow (mincapacity);} /** * Maximum capacity assigned to arrays * Why subtract 8? * Because some VMS retain some headers in the array, attempting to allocate this maximum storage capacity may result in an array capacity greater than the limit of the VM, resulting in OutOfMemoryError. */private static final int max_array_size = integer.max_value-8;/*** expansion to ensure that ArrayList can store at least mincapacity elements * First expansion, The logic is newcapacity = oldcapacity + (oldcapacity >> 1), which increases by half on the original capacity basis. After the first expansion, if the capacity is still less than mincapacity, the capacity is expanded to mincapacity. * * @param mincapacity desired minimum capacity */private void grow (int mincapacity) {//Gets the capacity of the current array int oldcapacity = Elementdata.leng Th Expansion. New capacity = current capacity + current capacity/2. The current capacity will be increased by half. int newcapacity = oldcapacity + (oldcapacity >> 1); If the capacity after expansion is still less than the desired minimum capacity if (Newcapacity-mincapacity < 0)//expansion capacity is again expanded to the desired minimum capacity newcapacity = Mincapaci Ty If the capacity after expansion is greater than the critical value, then bulk allocation 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);} /*** Bulk allocation */private static int hugecapacity (int mincapacity) {//If mincapacity<0, throws exception if (Mincapacity < 0)//overflow throw new Outofme Moryerror (); If the desired capacity is greater than max_array_size, assign Integer.max_value, otherwise assign max_array_size return (Mincapacity > Max_array_size)? Integer.MAX_VALUE:MAX_ARRAY_SIZE;
After reading the code, the expansion method can be summarized as follows:
- Conduct space checks to determine whether to scale and determine the minimum required capacity
- If the expansion is determined, execute
grow(int minCapacity)
, mincapacity to the minimum required capacity
- The first expansion, the logic of the
newCapacity = oldCapacity + (oldCapacity >> 1);
original capacity based on the increase in half.
- After the first expansion, if the capacity is still less than mincapacity, the capacity is expanded to mincapacity.
- The capacity after expansion is judged, if it is greater than the maximum allowable capacity max_array_size, the capacity is again adjusted to max_array_size. The expansion operation ends at this point.
Add (int index, E Element)
/** * Insert elements in the development position. The element at the current position and the element after index move backward one * * @param index is about to insert the element's position * @param element that is about to be inserted * @throws indexoutofboundsexception if the index exceeds size */public void Add (int index, E Element) { //cross check rangecheckforadd (index); Confirm list capacity, if not enough, capacity plus 1. Note: Add only 1 to ensure that resources are not wasted ensurecapacityinternal (size + 1); Increments modcount!! The array is copied and processed to empty the index position into element and the element after the index is shifted one position system.arraycopy (elementdata, index, Elementdata, index + 1,size-index); Assigns the specified index position to element Elementdata[index] = element; Actual capacity +1 size++;}
As you can see from the source code, add (e) has three steps:
- Cross Check
- Space checks, if necessary, to enlarge
- inserting elements
Cross-border checks are simple.
private void Rangecheckforadd (int index) { if (Index > Size | | Index < 0) throw new indexoutofboundsexcept Ion (Outofboundsmsg (index));}
add(int index, E e)
You need to move the element first and then complete the insert operation, which means that the method has a linear time complexity, which is O (n).
Remove (int index)
/** * Delete the element in list where the position is the index at the specified indices * The element that follows the index moves to the left one * * @param index of the deleted element * @return deleted element * @throws indexoutofboundsexception If the parameter specifies an index of index>=size, throw an out-of-bounds exception */public E remove (int index) {//Check whether the index is out of bounds. Throws an out-of-bounds exception Rangecheck (index) If the parameter specifies index index>=size; Number of structural modifications +1 modcount++; The record index is an element at Inde E oldValue = elementdata (index); The number of elements that need to be left shifted after the specified element is deleted int nummoved = size-index-1; If there is an element that needs to move left, it is moved (after moving, the deleted element is already overwritten) if (nummoved > 0) system.arraycopy (elementdata, index+1, Elementdata, Ind EX, nummoved); Size minus one, and then the element indexed as SIZE-1 is set to null. In order for the GC to work, you must explicitly assign a null value to the last location elementdata[--size] = null; Clear to let GC do it work//return the deleted element return oldValue;} /** * Cross-border check. * Check whether the index given is out of bounds. * Throws a run-time exception if it is out of bounds. * This method does not check whether index is legal. such as whether it is negative. * If the given index index>=size, throw an out-of-bounds exception */private void rangecheck (int index) {if (index >= size) throw new Indexout Ofboundsexception (outofboundsmsg (index));}
After reading the code, you can summarize the steps of ArrayList to delete the elements of the specified index as
- Check that the index is out of bounds. Throws an out-of-bounds exception if the parameter specifies an index index>=size
- Moves the element with index greater than index to the left one (after moving left, the deleted element is overwritten, which is equivalent to being deleted).
- Set the element at index size-1 to null (for GC to work).
Note: In order for the GC to work, you must explicitly assign a null value to the last location. If you do not manually assign a null value in the code above, the original object will not be reclaimed until the corresponding position is overwritten by another element.
Set (int index, E Element)
/** * Replace the element of the specified index * * @param the index of the substituted element * @param element is about to be replaced with the elements of the specified index * @return return the replaced element * @throws Indexoutofboundsexception as The result parameter specifies the index index>=size, throws an out-of-bounds exception */public e set (int index, E Element) { //checks whether the index is out of bounds. Throws an out-of-bounds exception Rangecheck (index) If the parameter specifies index index>=size; Record the substituted element E oldValue = elementdata (index); Replace element Elementdata[index] = element; Returns the replaced element return OldValue;
Java8 Source-arraylist