Deep into the ArrayList of collection

Source: Internet
Author: User
Tags addall array length concurrentmodificationexception
ArrayList of the collection

The collection is one of the most frequently used classes in the JDK, and the understanding of its specific implementation forms has been floating on the surface. So look at several collections of the source code (I JDK8 as a reference source) after the next few posts. and ArrayList as a frequent use of the list, is rightly the first resolution goal:

The composition of a class is a member variable and a member method, and subdivision is the construction method and other methods. A class cannot get rid of building an instance with a constructor unless it uses a static factory generation instance. Therefore, the collection class is learned later in order from member variables to constructor methods to other methods. member Variable

 /** * Default initial capacity.

    * Default initial capacity, that is, the size of the corresponding array * * private static final int default_capacity = 10;
     /** * Shared Empty array instance used for empty instances.

    * A shared empty array prepared for a blank instance (the empty ArrayList elementdata all point to this blank array) * * private static final object[] Empty_elementdata = {}; /** * Shared Empty array instance used for default sized empty.
     We * Distinguish this from empty_elementdata to know how much to inflate when * the-a-is added.  * An empty array prepared for the default null instance, and empty_elementdata the only difference is that when the first element is added *, the length of the array elementdata is extended to the private static final object[]

    Defaultcapacity_empty_elementdata = {};
     /** * The array buffer into which the elements of the ArrayList are stored. * The capacity of the ArrayList is the length of this array buffer. any * empty ArrayList with elementdata = = Defaultcapacity_empty_elementdata * 'll be expanded to Default_capaci
     TY is added.* The array in which the elements in the ArrayList are actually stored. The ArrayList capacity is the length of this array. When a blank * ArrayList and its elementdata adds the first element to Defaultcapacity_empty_elementdata, the length of the array is extended to transient OBJ Ect[] Elementdata; Non-private to simplify nested class access/** * The size of the ArrayList (the number of elements it contai
     NS). * The size of the ArrayList * @serial * * private int size;
Construction Method

Non-parametric constructs

Public ArrayList () {
       this.elementdata = defaultcapacity_empty_elementdata;
   }

Initializes an empty ArrayList, but capacity is 10 when the first element is added.

The method of constructing the parameter as capacity

Public ArrayList (int initialcapacity) {
       if (initialcapacity > 0) {
           this.elementdata = new object[ Initialcapacity];
       } else if (initialcapacity = = 0) {
           this.elementdata = empty_elementdata;
       } else {
           throw new Illegalargumentexce Ption ("Illegal Capacity:" +
                                              initialcapacity);
       }
   

Initializes a different array based on the initialization of the capacity.

The method of constructing the parameter as collection

Public ArrayList (COLLECTION< extends e> c) {
       elementdata = C.toarray ();
       if (size = elementdata.length)!= 0) {
           //C.toarray might (incorrectly) not return object[] ("=")
           if 6260652 Mentdata.getclass ()!= object[].class)
               elementdata = arrays.copyof (elementdata, size, object[].class);
       Else {
           //Replace with empty array.
           This.elementdata = Empty_elementdata;
       }
   

Because ArrayList operations are actually converted to elementdata operations. So you can see the key to this construction method is the operation of ToArray () and arrays.copyof (). In addition, it is simply to judge the type of the collection elements, default to type object, and if not, re sculpt. other member Methods

Among the many methods, we first introduce some of the most frequently used, most closely involved. ToArray ()

Public object[] ToArray () {return
        arrays.copyof (elementdata, size);
    }

The key to converting ArrayList into arrays is undoubtedly in arrays.copyof (), except that the type of array that is converted by default is the same as the Elementdata element type. arrays.copyof ()

public static <T,U> t[] copyof (u[] original, int newlength, class<? extends t[]> NewType) {
        @SuppressWarni NGS ("unchecked")
        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;
    }

If Newtype is the object class, create a new object array with a length of newlength. If not, the native method is used to generate the corresponding type array based on the ComponentType and length. Then use the native method to transfer the data from the source array to the new array. dynamic expansion of array

/* Public method, where an object can invoke the expansion outside. There are three cases of an array: 1, the initial value is Empty_elementdata 2, the initial value is Defaultcapacity_empty_elementdata 3, non-empty array if the source array is case 1 or 3, the argument will be Mincapa
    City generation into the expansion. If the source array is 2, the default minimum extension is 10, and the mincapacity is expanded after comparison with 10.
Here you can see the difference between the source array and the Defaultcapacity_empty_elementdata. */public void ensurecapacity (int mincapacity) {int minexpand = (Elementdata!= defaultcapacity_empty_elementdata )//any size if not default element table? 0//Larger than default for default empty table.
            It ' s already//supposed to is at default size.

        : default_capacity;
        if (Mincapacity > Minexpand) {ensureexplicitcapacity (mincapacity); }/* The expansion operation before the array is increased.
        If the source array is defaultcapacity_empty_elementdata, the default expansion to size is 10.
    If the mincapacity is larger than the defaul_capacity, it is enlarged to mincapacity. */private void ensurecapacityinternal (int mincapacity) {if elementdata = = Defaultcapacity_empty_elementdata ) {mincapacity = Math.max (default_capacity, mincapacity);
    } ensureexplicitcapacity (mincapacity);

        }///Final call array expansion private void ensureexplicitcapacity (int mincapacity) {modcount++;
    Overflow-conscious code if (mincapacity-elementdata.length > 0) grow (mincapacity);
     }/** * The maximum size of array to allocate.
     * Some VMs Reserve Some header words in an array.
    * Attempts to allocate larger arrays could result in * outofmemoryerror:requested array size exceeds VM limit * *

    private static final int max_array_size = integer.max_value-8;
     /** * The actual operation of the expansion of the array * compares the mincapacity and the length of the source array 1.5 times times (actually to the right one bit, approximately 0.5 times times), and takes a larger value.
     * If the newcapacity is larger than the max_array_size, enter the Hugecapacity () method to take the extended array size.
     * Finally, use arrays.copyof () to generate a new array of length newcapacity, and the content is the source array content. * * private void grow (int mincapacity) {//overflow-conscious code int oldcapacity = Elementdata.lengt
       H int newcapacity = oldcapacity + (oldcapacity >> 1);
        if (newcapacity-mincapacity < 0) newcapacity = mincapacity;
        if (newcapacity-max_array_size > 0) newcapacity = hugecapacity (mincapacity);
    Mincapacity is usually the close to size, so this is a win:elementdata = arrays.copyof (Elementdata, newcapacity);
    }//expansion of smaller parameters than int, then throw error//otherwise give a maximum limit. private static int hugecapacity (int mincapacity) {if (mincapacity < 0)//overflow throw new outof
        Memoryerror ();
            Return (Mincapacity > Max_array_size)?
    Integer.MAX_VALUE:MAX_ARRAY_SIZE;
 }

The above code can echo the constructor method, when Elementdata is Defaultcapacity_empty_elementdata, as long as the array expansion occurs, the default expansion to the array length is 10. list additions and deletions method

e elementdata (int index) {return (e) Elementdata[index];

        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;
    return oldValue;
    ///Add to the tail of the array, first to expand the array, and then directly to the index for size++.  Public boolean Add (E e) {ensurecapacityinternal (size + 1);
        Increments modcount!!
        elementdata[size++] = e;
    return true; ///The array expands first, then uses the native method to copy the array from the value from the index to the beginning of the index+1, and then add the index//new element public void Add (int index, E elemen

        T) {Rangecheckforadd (index);  Ensurecapacityinternal (size + 1);
        Increments modcount!!
        System.arraycopy (Elementdata, index, Elementdata, index + 1, size-index);
        Elementdata[index] = element;
    size++; }//is almost an increased reverse process, or a arraycopy method. Copy the value after index to the index start's location.
    You need to be aware of eliminating references to prevent memory from being recycled.

        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, n
        ummoved); Elementdata[--size] = null;
    Clear to let GC does its work return oldValue;
    //Traverse to find the index value of the first object, and then delete it according to index. Also need to be aware of removing the application public boolean remove (Object o) {if (o = = null) {for (int index = 0; index < siz E
                    index++) if (elementdata[index] = = null) {fastremove (index);
                return true; } else {for (int index = 0; index < size; index++) if (o.equals) (Elementdata[inde
                    X])) {fastremove (index);
                return true; } return False;
    The Delete method for the return value is not required.
        private void Fastremove (int index) {modcount++;
        int nummoved = size-index-1; if (nummoved > 0) system.arraycopy (elementdata, index+1, Elementdata, index, n
        ummoved); Elementdata[--size] = null;

        The clear to let GC does its work} is public void clear () {modcount++;

        Work for (int i = 0; i < size; i++) elementdata[i] = null;
    size = 0; The//procedure is similar: array expansion, add the new C to the array A to the elementdata tail.
    Also through the Arraycopy method.
        public boolean addall (COLLECTION&LT; extends e> c) {object[] a = C.toarray ();
        int numnew = A.length;  Ensurecapacityinternal (size + numnew);
        Increments Modcount system.arraycopy (A, 0, elementdata, size, numnew);
        Size + = Numnew;
    return numnew!= 0;
    //STEP1: Array expansion//STEP2: After the array index after the content move//step3: Copy the new array C content to Elementdata. PubliC boolean addall (int index, COLLECTION&LT;? extends e> c) {rangecheckforadd (index);
        Object[] A = C.toarray ();
        int numnew = A.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);
        work int newsize = size-(TOINDEX-FROMINDEX);
        for (int i = newsize i < size; i++) {elementdata[i] = null;
    size = newsize; }

From the above add and delete operation code, you can see that the operation involved mainly on the increase in the dynamic expansion of the array and the use of the System.arraycopy () method of array movement (essentially also array replication) and the use of the same system.arraycopy ( Completes array movement and eliminates array references. iterator

 Public listiterator<e> listiterator (int index) {if (Index < 0 | | index > size) throw new
        Indexoutofboundsexception ("Index:" +index);
    return new Listitr (index);
     }/** * Returns a list iterator over the elements in this list (in proper * sequence).
     * * <p>the returned list iterator is <a href= "#fail-fast" &GT;&LT;I&GT;FAIL-FAST&LT;/I&GT;&LT;/A&GT;.
    * * @see #listIterator (int) */public listiterator<e> Listiterator () {return new Listitr (0);
    /** * Returns an iterator */public iterator<e> iterator () {return new Itr ();       /** * Rewrite the implementation class of the Iteartor interface * * Private class ITR implements iterator<e> {int cursor; The next return element position int lastret =-1;

        The position of the last returned element int expectedmodcount = Modcount;
        public Boolean Hasnext () {return cursor!= size;
       On///Initialize, return starting from index 0. @SuppressWarnings ("unchecked") public E Next () {checkforcomodification ();
            int i = cursor;
            if (i >= size) throw new nosuchelementexception ();
            object[] Elementdata = ArrayList.this.elementData;
            if (i >= elementdata.length) throw new Concurrentmodificationexception ();
            cursor = i + 1;
        Return (E) Elementdata[lastret = i]; //Remove the currently pointing to location element public void Remove () {if (Lastret < 0) throw new Illegalsta
            Teexception ();

            Checkforcomodification ();
                try {ArrayList.this.remove (Lastret);
                cursor = Lastret;
                Lastret =-1;
            Expectedmodcount = Modcount;
            The catch (Indexoutofboundsexception ex) {throw new concurrentmodificationexception (); }} @Override @SuppressWarnings ("Unchecked ") public void Foreachremaining (consumer&lt. Super e> Consumer) {objects.requirenonnull (consum
            ER);
            final int size = ArrayList.this.size;
            int i = cursor;
            if (i >= size) {return;
            Final object[] Elementdata = ArrayList.this.elementData;
            if (i >= elementdata.length) {throw new concurrentmodificationexception (); while (i!= size && modcount = = Expectedmodcount) {consumer.accept ((E) elementdata[
            i++]);
            }//Update once at the iteration to reduce heap write traffic cursor = i;
            Lastret = i-1;
        Checkforcomodification (); final void Checkforcomodification () {if (Modcount!= expectedmodcount) throw new C
        Oncurrentmodificationexception ();
     }/** * supports traversal from a certain index and can be accessed forward.
*/    Private class Listitr extends Itr implements listiterator<e> {listitr (int index) {super ();
        cursor = index;
        public Boolean hasprevious () {return cursor!= 0;
        public int Nextindex () {return cursor;
        public int Previousindex () {return cursor-1;
            @SuppressWarnings ("unchecked") public E Previous () {checkforcomodification ();
            int i = cursor-1;
            if (I < 0) throw new nosuchelementexception ();
            object[] Elementdata = ArrayList.this.elementData;
            if (i >= elementdata.length) throw new Concurrentmodificationexception ();
            cursor = i;
        Return (E) Elementdata[lastret = i];
            The public void set (E e) {if (Lastret < 0) throw new IllegalStateException (); CheckforcomOdification ();
            try {ArrayList.this.set (Lastret, E);
            The catch (Indexoutofboundsexception ex) {throw new concurrentmodificationexception ();

            } public void Add (e e) {checkforcomodification ();
                try {int i = cursor;
                ArrayList.this.add (i, E);
                cursor = i + 1;
                Lastret =-1;
            Expectedmodcount = Modcount;
            The catch (Indexoutofboundsexception ex) {throw new concurrentmodificationexception (); }
        }
    }

The

Use iterators intended to guarantee consistent traversal access without exposing the internal implementation of the class.

Traversal delete problem public static list<string> initiallist () {list<string> List = new arraylist<> ();
        List.add ("a");
        List.add ("B");
        List.add ("C");
        List.add ("D");
    return list;
            public static void Removebyfor (List<string> List) {for (int i = 0; i < list.size (); i++) {
                if ("B". Equals (List.get (i))) {System.out.println (i));
            List.remove (i);
                } if ("D". Equals (List.get (i)) {System.out.println (i));
            List.remove (i);
    } System.out.println (list); public static void Removebyforeach (List<string> List) {for (String string:list) {if ("
            B ". Equals (String)) {List.remove (string);
    } System.out.println (list); public static void Removebyiterator (List<string>list) {iterator<string> e = list.itErator ();
            while (E.hasnext ()) {String item = E.next ();
            if ("B". Equals (item)) {E.remove ();
    } System.out.println (list);         public static void Main (String []args) {removebyfor (Initiallist ()); 1 Removebyforeach

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.