Reprinted from Java8 ArrayList source reading
This article is based on jdk1.8
There are three classes in the Java collection library:list,queue,set
Where list, there are three sub-implementation classes:arraylist,vector,linkedlist
Http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/tip/src/share/classes/java/util/ArrayList.java
Implementation principle
transient Object[] Elementdata; // an array of elements to store Private int size; // the number of elements actually stored
The ArrayList layer uses an array of type object to hold the data, and the size variable represents the number of elements that the list actually holds
Add,remove,get,set,contains operation
Both the get and set methods are used to manipulate the data directly by array subscript, and the time Complexity is O (1).
Public Booleancontains (Object o) {returnIndexOf (o) >= 0;} Public intindexOf (Object o) {//Traverse all elements to find the same element, return the subscript of the element,//if the element is null, the address is directly compared, otherwise the Equals method is used to compare if(O = =NULL) { for(inti = 0; i < size; i++) if(elementdata[i]==NULL) returni; } Else { for(inti = 0; i < size; i++) if(O.equals (Elementdata[i]))returni; } return-1;}
Add
Public BooleanAdd (e e) {ensurecapacityinternal (size+ 1);//Expansion Detectionelementdata[size++] = e;//adding new elements to the end return true;} Public voidAddintindex, E Element) {Rangecheckforadd (index); Ensurecapacityinternal (Size+ 1);//Expansion Detection//using the System.arraycopy method, move the element behind the index 1 bits backwardsSystem.arraycopy (Elementdata, index, Elementdata, index + 1, size-index); Elementdata[index]= element;//store element to index positionsize++;}
Remove
PublicE Remove (intindex) {Rangecheck (index); //cross-border detectionModcount++; E OldValue= Elementdata (index);//Old value intnummoved = size-index-1;//number of elements that need to be moved if(nummoved > 0) system.arraycopy (elementdata, index+1, Elementdata, Index, nummoved); elementdata[--size] =NULL;//allows the JVM to perform GC operations to avoid leaks returnOldValue;}
Scaling strategy
The ArrayList is stored using an array, and the expansion occurs when the array size is not sufficient to hold the new element.
In the add operation, the ArrayList first calls the Ensurecapacityinternal method for the expansion detection.
If the array size is insufficient, the expansion is automatic, and if the size after expansion exceeds the maximum size of the array, an exception is thrown.
Ensurecapacityinternal (size + 1);
ArrayList expansion plan, there are two steps:1. Size detection, 2. Expansion
Private voidEnsurecapacityinternal (intmincapacity) { //arraylist<integer> a = new arraylist<integer> () or read by serialization, the element size is 0 o'clock, the underlying array is a null array//if the underlying array size is 0, the default capacity size is used if(Elementdata = =empty_elementdata) {mincapacity=Math.max (default_capacity, mincapacity); } ensureexplicitcapacity (mincapacity);}Private voidEnsureexplicitcapacity (intmincapacity) { //data structure changes, and fail-fast mechanism, in the use of iterators, only through the method of iterators (such as iterators add,remove, etc.), modify the data structure of the list,//If you use the list method (such as add,remove in list), modifying the data structure of the list will throw Concurrentmodificationexceptionmodcount++; //the Grow method is called when the current array size is insufficient, and automatic expansion if(Mincapacity-elementdata.length > 0) grow (mincapacity);}Private Static Final intMax_array_size = integer.max_value-8;Private voidGrowintmincapacity) { //overflow-conscious Code intOldcapacity =elementdata.length; //new capacity size = 1.5 times times the size of the original capacity intNewcapacity = oldcapacity + (oldcapacity >> 1); if(Newcapacity-mincapacity < 0)//overflow judgment, such as Mincapacity = INTEGER.MAX_VALUE/2, oldcapacity = minCapacity-1Newcapacity =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 intHugecapacity (intmincapacity) { if(Mincapacity < 0)//Overflow Throw NewOutOfMemoryError (); return(Mincapacity > Max_array_size)?Integer.MAX_VALUE:MAX_ARRAY_SIZE;}
Implementation of Fail-fast mechanism
The fail-fast mechanism, also known as the "fast failure" mechanism, is an error detection mechanism in the Java collection.
In the iterative process of the collection, in addition to iterators can be modified on the data structure of the collection, and other changes to the data structure of the collection, will throw concurrentmodificationexception error.
Here, the so-called 进行数据结构上进行修改
, refers to the stored object, the Add,set,remove operation, and then the data changes.
ArrayList, there is a modcount variable, each time add,set,remove and other operations, will be executed modcount++.
When you get an iterator for ArrayList, the Modcount in ArrayList is saved in the iteration.
Each time you perform an operation such as Add,set,remove, a check is performed, the Checkforcomodification method is called, and the Modcount is compared.
If the modcount in the iterator and the Modcount in the list are different, the concurrentmodificationexception is thrown
Final void checkforcomodification () { if (expectedmodcount! = ArrayList. This. Modcount) thrownew concurrentmodificationexception ();
Usage Scenarios
ArrayList's usage scenarios are mainly considered in terms of their pros and cons:
Advantages:
Get,set, Time complexity O (1)
Add (usually inserted at the end), Time complexity O (1), worst case (insert data to head), Time complexity O (n)
The data store is sequential
Disadvantages:
Remove, time complexity O (n), best case (remove end element), Time complexity O (1)
ArrayList the bottom layer uses arrays to store data, arrays are not automatically expandable, so in the case of expansion, a large number of elements need to be moved.
When the ArrayList size is large, there is a waste of space (you can clear the free space by TrimToSize method)
The size of the array is limited by the JVM and the machine, and ArrayList throws an exception when the expansion exceeds the upper limit.
Insert operations, data volume is small, in order to store, you can consider using ArrayList
In the case of multithreading:
ArrayList all operations are not synchronous, so ArrayList is not thread-safe.
If you consider thread safety, you can use copyonwritearraylist or an external sync ArrayList (List list = Collections.synchronizedlist (new ArrayList (...)); )
Thinking
In the 1.remove method, why is the element corresponding to the array set to NULL?
ArrayList internal use of arrays to implement a set of Management objects mechanism, the remove operation, the number of elements has been-1, ArrayList that the object has been removed, should be recycled by the JVM.
However, for the JVM, the value is still stored in the array, and ArrayList holds a reference to the object, which is not recycled by the JVM when the JVM is in GC, which results in a memory leak.
2. In the method of finding the element (such as indexof), why do I need to determine the null value of the element?
Determine if the object is equal, there are two aspects, 1. The address of the object store; 2. The contents of the object.
= =, is used to compare the address of two objects is equal, generally speaking, the address of two objects is the same, then the two objects can be considered the same object
The Equals method, which is used to compare the contents of an object, can, of course, overload the method and directly compare the object's address; the Equals method of the object is the comparison address.
In general, overloading the Equals method while overloading the Hashcode method with the overloaded Hashcode method must follow 6 principles:
Reflexivity: Must return true for any non-null reference value X,x.equals (x)
Transitivity: For any non-null reference value x, Y, Z, if X.equals (y) is true, and Y.equals (z) is true, then X.equals (z) must be True
Symmetry: For any non-null reference value x, Y, if X.equals (y) is true, then y.equals (x) must be True
Non-nullability: x,x.equals (NULL) must be false for any non-null reference value
Consistency: For any non-null reference value, x, Y, if you call the Equals method multiple times, if the value of x and Y is not changed, then X.equals (y) will be consistent to return true or false
Why overload the Equals method, typically overloading the Hashcode method?
Overloaded with the Equals method, you can not overload the Hashcode method, but in general, this is not recommended.
Hashcode method, use to find out the object's hash value,
The overloaded Hashcode method is primarily designed to improve the efficiency of some containers (such as hashmap,hashtable) for hashing, and also to avoid errors (such as the operation of HashSet containers).
For the null value of the element to judge, I think mainly for efficiency considerations, if it is a null value, you can directly compare the address, not the null value, you need to compare by the Equals method, because ArrayList is generic,
So its added elements may overload the Equals method, customizing the principle of judgment.
In the 3.grow method, the new capacity size is judged, why is the max_array_size defined?
ArrayList the underlying storage is implemented using arrays, so the size of the ArrayList storage file is bound to be limited by the size of the array, so in the expansion, you can see ArrayList to the new capacity size of the logical judgment.
affect the maximum value of the array:
Theoretical maximum value is integer.max_value (2^32-1)
Object header limits, different types of elements, the maximum value that can be created for an array is different, byte is 1 bytes, int is 4 bytes
For example, the JVM available memory is 1m,32 bit machine,
int New int [1024x768 * 1024/4]; byte New byte [1024 * 1024];
JVM Available Memory size limit
For example, the JVM available memory is 1m,32 bit machine,
byte byte [1024 * 1024]
As for why max_array_size = integer.max_value-8;
Mainly in 64 for the machine, the object of the
Java8 ArrayList Source Reading