ArrayList is a variable long array implementation of the List interface. Implement all LIST interfaces and allow storage NULL values. In addition to not being synchronized, ArrayList is basically equivalent to Vector. Almost all methods are almost synchronized in the Vector, but ArrayList is only synchronized with WriteObject and ReadObject, such as add (object), remove (int), etc. is not synchronized.
1. Store ArrayList to use an Object's array storage element.
Private Transient Object ElementData [];
ArrayList implements the java.io.serializable interface, which is not required to automatically serialize this property. The following will explain this in the WriteObject () method.
2.Add and Remove
public
Boolean Add (Object O) {
EnsureCapacity (SIZE 1);
// increments modcount !!
ElementData [Size ] = O;
Return
True;
}
Note that the EnSureCapacity () method here, its role is to ensure that the length of the ElementData array can accommodate a new element. Take a detailed explanation in the "Automatic Aspect Mechanism".
Public Object Remove
INT index) {
RangeCheck (index);
MODCOUNT ;
Object 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;
}
The role of RangeCheck () is to perform border checks. Since ArrayList uses an object array storage element, you need to move the back element before deleting an element. When deleting an element, it is only set to NULL in the ElementData array, and the specific object is destroyed by the garbage collector.
The role of Modcount will be described in the "synchronization" of iTerator ().
Note: A practical method provided by SYSTEM: arraycopy (), in this case, can see the SYSTEM.ARRAYCOPY () method can operate the same array, this method is a native method, if When an array operates, copy the source part to a temporary array, copy the element of the temporary array to the target location.
3. Automatic growth mechanism When instanting an ArrayList, you can specify an initial capacity. This capacity is the initial length of the ElementData array. If you use:
ArrayList List =
New arraylist ();
Use the default capacity: 10.
Public arraylist () {
THIS (10);
}
ArrayList provides four add () methods,
Public Boolean Add (Object O) Public Void Add (INDEX, Object Element) Public Boolean Addall (Collection C) Public Boolean Addall (Int Index, Collection C)
In each add () method, a EnsureCapacity (Int minicaPacity) method is first called, this method guarantees that the ElementData array is not less than Minicapacity. The automatic growth mechanism of ArrayList is implemented in this method. public
Void EnsulectriCity
INT minCapacity) {
MODCOUNT ;
Int Oldcapacity = ElementData.Length;
IF (MINCAPACITY> Oldcapacity) {
Object olddata [] = elementdata;
INT newcapacity = (Oldcapacity * 3) / 2 1;
NewCapacity Newcapacity = mincapacity; ELEMENTDATA = New Object [ Newcapacity]; System.ArrayCopy (OldData, 0, ElementData, 0, size); } } From this method implementation, it can be seen that ArrayList is expanded to 1.5 times that of the original size. The implementation of each ADD () method is similar, and the implementation of the Add (Object) method is given below: public Boolean Add (Object O) { EnsureCapacity (SIZE 1); // increments modcount !! ElementData [Size ] = O; Return True; } 4. Synchronization inTerator () Defines an INT type attribute in the parent class AbstractList: Modcount, which records the number of ArrayList structural changes. protected TRANSIENT INT MODCOUNT = 0; In all methods of ArrayList involve structural changes, the value of modcount is increased, including: add (), remove (), addall (), removerange (), and clear () method. Each of these methods is called once, and the value of Modcount is added 1. Note: The value of the modcount of the add () and addall () methods is incremented in the EnSureCapacity () method called. The item () method (ArrayList directly inherits this method) in AbstractList uses a private internal member class ITR to generate an ITR object (Iterator interface) returns: Public iterator itrator () { Return New ITR (); } The ITR implements the Iterator () interface, which also defines an INT type attribute: ExpectedModCount, which is given the value of the Modcount property of the ArrayList object when ITR class is initialized. INT EXPECTEDMODCOUNT = MODCOUNT; Note: Internal membership ITR is also a member of the ArrayList class, which can access all AbstractList properties and methods. Understand this, the implementation of the ITR class is easily understood. In the itr.hasnext () method: public Boolean Hasnext () { RETURN CURSOR! = size (); } The Size () method of the AbstractList is called, and the current cursor position is the crosstalk. In the ITr.next () method, ITR also calls the Get (int) method defined in AbstractList, returning the element at the current cursor: public object next () { Try { Object next = GET (CURSOR); CheckForComodification (); Lastret = CURSOR ; Return NEXT; } Catch (indexoutofboundsexception e) { CheckForComodification (); Throw New nosuchelementexception (); } } Note that the checkforcomodification () method is called in the next () method, and the synchronization check for the modification is performed: Final Void CheckForComodification () { IF (MODCOUNT! = EXPECTEDMODCOUNT) Throw New concurrentmodificationException (); } The role of Modcount and ExpectedModCount is now very clear. While falling in a collection object, it is not limited to operation of the elements of the collection object, including some hazardous operations such as add () or remove () that may cause a drop-down error. In AbstractList, a simple mechanism is used to avoid these risks. This is the role of Modcount and ExpectedModCount. 5. Serialization support ArrayList implements the java.io.Serializable interface, so the ArrayList object can be serialized into a persistent storage medium. The main attributes of ArrayList are defined as follows: Private static final long serialversionuid = 8683452581122892189l; private tar ibject elementdata []; private int size It can be seen that both SerialVersionUID and SIZE will automatically serialize into the media, but the ElementData array object is defined as transient. That is to say, all of these elements in ArrayList are automatically serialized into the medium. Why do you implement this? Because the "element" stored in the ElementData is actually only a reference to these elements, it is not true object, and the serialization of an object is meaningless, because serialization is in deserialization, when you degrade sequence The reference to these objects is not possible to point to the original object. Therefore, you need to manually serialize the elements of arraylist here. This is the role of WRITEOBJECT (). Private SYNCHRONIZED Void writeObject (java.io.objectOutputstream s) Throws java.io.ioException { // Write Out Element Count, And Any Hidden Stuff s.defaultwriteObject (); // Write out Array Length S.WriteInt (ElementData.length); // Write out all Elements in the project. FOR INT i = 0; i S.WriteObject (ElementData [i]); } Such elemental array ElementData can be properly serialized to storage media. The corresponding readObject () is also read from the input stream in the order of the WriteObject () method: PrivateSynchronized Void ReadObject (java.io.objectInputStream S) THROWS JAVA.IO.IException, classnotfoundexception { // read in size, and any hidden stuff S.DEFAULTREADOBJECT (); // read in Array Length And Allocate Array Int arraylength = s.readint (); ELEMENTDATA = New Object [ArrayLength]; // read in All Elements in The Proper ORDER. FOR INT i = 0; i ElementData [I] = s.readObject (); }