Java Collection ArrayList source code Analysis __java

Source: Internet
Author: User
Tags int size serialization shallow copy

The collection is a very important and fundamental element in Java, usually we use the most, its usage is very simple, will use one, the basic other is very easy, thanks to the design of the set frame, since the first step has been used, then it is necessary to understand, learn its design skills, understand its essence, This will not only use, but also will use better, with a deeper understanding, then the use of the process are very clear, rather than using a random, if there are problems, but also easy to troubleshoot, today we began the Java Collection framework of the adventure trip.

Speaking of the Java collection, we estimate the following figure that you are most familiar with, which I found from the Internet.

This figure is very image, basically look at this graph to be able to roughly understand the relation in the Java set, start from ArrayList first. ArrayList (JDK 1.8)

ArrayList is the most common collection class, a dynamic array, as the name suggests, ArrayList is a collection that is implemented as an array. Inheritance System

ArrayList inherits the Abstractlist,implements List,serializable,randomaccess,cloneable interface. Interesting phenomena will be found: Abstractlist is implements the list interface, and ArrayList also implements the list interface again.
Random access list (random access lists), ArrayList is random access, so you need to play this tag, corresponding to the sequence access list (sequential access lists).
Serializable,cloneable indicates that ArrayList can be serialized, cloned. Data Structure

element function
Transient object[] Elementdata ArrayList is an implementation based on an array, elementdata is the underlying array
private int Size The number of elements inside the ArrayList

The operation of the ArrayList is actually the operation of the array, except that it can be dynamically expanded. Initial Construction

    /**
     * Constructs a empty list with an initial capacity of ten.
     * * Public
    ArrayList () {
        this.elementdata = defaultcapacity_empty_elementdata;
    }

An parameterless construct in which the underlying array points to an empty array.

    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);
        }
    

You can also specify an initial size, then ArrayList will generate an array of initialcapacity sizes. Dynamic Expansion

Let's take a look at how ArrayList is expanding.

    /**
     * Increases the capacity to ensure, it can hold at least the
     * number of elements specified by the minimum Capacity argument.
     *
     * @param mincapacity the desired minimum capacity * *
    private void Grow (int mincapacity) {
        //Overflow-c onscious code
        int oldcapacity = elementdata.length;
        int newcapacity = oldcapacity + (oldcapacity >> 1);
        if (newcapacity-mincapacity < 0)
            newcapacity = mincapacity;
        if (newcapacity-max_array_size > 0)
            newcapacity = hugecapacity (mincapacity);
        Mincapacity is usually close to size, and so is a win:
        Elementdata = arrays.copyof (Elementdata, newcapacity); 
  }

The size of the element group changed to 1.5 times times when it was enlarged.

    public static <T> t[] copyof (t[] original, int newlength) {return
        (t[)) copyof (original, Newlength, ORIGINAL.G Etclass ());
    }
    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;
    }

As you can see, the expansion of the array is simple, resulting in an array of the same length as the newlength, and then copying the data from the original array into the new array to complete the expansion function. This I personally think we should all be similar to the encapsulation of this kind of dynamic expansion function of the array. adding elements

    /**
     * Appends the specified element to the "end of" this list.
     *
     * @param e element to is appended to this list
     * @return <tt>true</tt> (as specified by {@link Colle Ction#add})
     */Public
    Boolean add (E e) {
        ensurecapacityinternal (size + 1);  Increments modcount!!
        elementdata[size++] = e;
        return true;
    }

The add is to add the element to the end of the array, before adding, check to see if expansion is required, and then put it at the end of the array, O (1) Time complexity

    public void Add (int index, E element) {
        Rangecheckforadd (index);

        Ensurecapacityinternal (size + 1);  Increments modcount!!
        System.arraycopy (Elementdata, index, Elementdata, index + 1,
                         size-index);
        Elementdata[index] = element;
        size++;
    }

Adds an element to the specified location, the first check is whether the index position is valid, which means that the data in the array will be moved, and then the data in the index will be pushed back one after another, and then the data will be inserted into the index position, which is an O (n) time complexity. The better the performance, the worse the reverse. Delete Element

    /**
     * Removes the element at the specified position into this list.
     * Shifts any subsequent elements to the "left" (subtracts one from their
     * indices).
     * * @param index The "the" is
     removed * @return The element that is removed from the
     list
     * @throws indexoutofboundsexception {@inheritDoc}
     */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 does its work return

        OldValue;
    }

Deletes the element at the specified position, first moving all elements behind the specified element, using the System.arraycopy method as a whole to move one position forward, and then specifying the element in the last position as NULL so that the GC can reclaim it.

    public boolean remove (Object o) {
        if (o = = null) {for
            (int index = 0; index < size; index++)
                if (ELEMENTDA Ta[index] = = null) {
                    fastremove (index);
                    return true;
                }
        else {for
            (int index = 0; index < size; index++)
                if (O.equals (Elementdata[index))) {
                    fastremove (index); C11/>return true;
                }
        }
        return false;
    }

By element deletion, by the Remove method, we know that ArrayList can be stored in null value, if the deletion is null, then it will be found inside the element of NULL to delete, Otherwise, the Equals method of the object will be called to determine whether two objects are equal (depending on whether or not to rewrite equals), fastremove name quickly delete, but the inside or the use of moving elements, in fact, is not fast.

Other similar methods, like additions and deletions, are essentially arrays of operations, so it's not going to start here. clones

ArrayList realized cloneable that this class can be cloned, see cloneable found nothing, in fact, cloneable I understand just a label, the surface of the class can be cloned, as to how to clone it regardless, in addition, in the object There is a clone method, so cloneable no need to have a clone interface, we can rewrite the parent clone method, as we asked for cloning, to see the ArrayList inside the clone.

    /**
     * Returns A shallow copy of this <tt>ArrayList</tt> instance.  (The
     * elements themselves are not copied.)
     *
     @return A clone of this <tt>ArrayList</tt> instance *
    /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);
        }
    

Is inherently simple, is the bottom of the array copy copy, so that a new ArrayList containing the same data, you can see this cloning is a shallow copy, as far as the depth of the copy here does not talk, originally I have in C + + research, blog inside also have, but may write the quality generally, For a deep copy, it's easy to understand the difference between a basic data type and a reference data type. Serialization of

ArrayList implements the Serializable, which means ArrayList can be serialized and propagated over the network, but let's look at the array in ArrayList, which is defined as:

Transient object[] elementdata; Non-private to simplify nested class access

Why Elementdata is decorated with transient. (attributes declared as transient are not serialized, which is the role of the Transient keyword)

Java does not force users to use the default serialization method, the user can also according to their own preferences to specify the serialization of their own way.
When serializing, deserializing, the virtual opportunity first attempts to invoke the WriteObject and ReadObject methods in the object, making user-defined serialization and deserialization. If there is no such method, then the default invocation is the ObjectOutputStream defaultwriteobject and the ObjectInputStream Defaultreadobject method. In other words, using the custom WriteObject method and the ReadObject method, users can control the serialization and deserialization process themselves.

Since Elementdata cannot be serialized automatically, it will be manually serialized, so let's look at the WriteObject method inside the ArrayList.

    /** * Save The state of the ' <tt>ArrayList</tt> instance to a stream (which is, serialize it). * * @serialData The length of the array backing the <tt>ArrayList</tt> * instance I s emitted (int), followed by all of its elements * (each a <tt>Object</tt>) in the proper or
     Der. * * private void WriteObject (Java.io.ObjectOutputStream s) throws java.io.ioexception{//Write out Ele
        ment count, and any hidden stuff int expectedmodcount = Modcount;

        S.defaultwriteobject ();

        Write out size as capacity to behavioural compatibility with clone () s.writeint (size);
        Write out all elements in the proper order.
        for (int i=0; i<size; i++) {s.writeobject (elementdata[i]);
        } if (Modcount!= expectedmodcount) {throw new concurrentmodificationexception (); }
    }

In fact, found that simple, writeobject only serialized in the Elementdata part of the data, in fact, this is still very easy to understand, ArrayList inside the elementdata may not be full, then it is necessary to serialize the entire elementdata it. Obviously not necessary, so the WriteObject method is overridden in ArrayList.
Of course, there is a corresponding deserialization ReadObject method, this is the reverse process of writeobject, here is no longer unfold, you can see for yourself. ArrayList and Abstractlist

ArrayList rewrite methods such as the indexof of the parent class, in Abstractlist, the IndexOf method is implemented by an iterator, and the sequence traversal of the array is implemented in ArrayList, and the reason for the rewrite is to speed. Because the ArrayList bottom is an array-implemented random access, the random access performance is higher than the iterator.

The IndexOf method in Abstractlist:

    public int indexOf (Object o) {
        listiterator<e> it = Listiterator ();
        if (o==null) {while
            (It.hasnext ())
                if (It.next () ==null) return
                    it.previousindex ();
        } else {
            while (It.hasnext ())
                if (O.equals (It.next ())) return
                    It.previousindex ();
        }
        return-1;
    }

The IndexOf method in ArrayList:

    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-1;
    }
Summary

Summarize the characteristics of ArrayList from the above process:

ArrayList stored data is allowed to be empty

ArrayList allows duplicate data to be stored

ArrayList store data in an orderly fashion (meaning that the order in which data is read is the same as the order in which it is stored)

ArrayList is not thread safe (operations on the underlying array are not synchronized)

Summarize the advantages and disadvantages of ArrayList. The advantages of ArrayList are as follows:

1, ArrayList the bottom of the array implementation, is a random access mode , the search is also the time is very fast

2, ArrayList in order to add an element of the time is very convenient, but to the array to add an element just

Disadvantages of ArrayList:

1, when the deletion of elements, involving a copy of the elements, if you want to copy a lot of elements, it will be more cost performance

2, when inserting elements, involves a copy of the element, if you want to copy a lot of elements, it will be more cost performance

Therefore, ArrayList is more suitable for sequential add, random access scenes.

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.