ArrayList source code analysis of Java Collection series, arraylist source code

Source: Internet
Author: User

ArrayList source code analysis of Java Collection series, arraylist source code

This article analyzes the source code of ArrayList. Before analyzing the source code, let's talk about arrays. An array may be one of the earliest data structures we have come into contact with. It divides a continuous address space in the memory for storing elements. Because it operates the memory directly, therefore, the array performance is better than the collection class, which is a major advantage of using arrays. However, we know that the array has a fatal defect, that is, the array size must be specified during initialization, And the array size cannot be changed in subsequent operations. In actual situations, we often encounter that we do not know how many elements to store at the beginning, but want the container to automatically expand its capacity so that it can store more elements. ArrayList can meet such requirements well. It can automatically expand the size to adapt to the increasing number of storage elements. Its underlying layer is implemented based on arrays, so it has some characteristics of arrays, such as fast search and modification, and slow insertion and deletion. In this article, we will go into the source code to see how it encapsulates arrays. First, let's take a look at its member variables and three major constructors.

// Default initialization capacity private static final int DEFAULT_CAPACITY = 10; // empty Object array private static final Object [] EMPTY_ELEMENTDATA ={}; // Object array private transient Object [] elementData; // private int size of the number of elements in the Set; // constructor for importing the initial capacity public ArrayList (int initialCapacity) {super (); if (initialCapacity <0) {throw new IllegalArgumentException ("Illegal Capacity:" + initialCapacity) ;}// create an array of the Object type of the specified Capacity this. elementData = new Object [InitialCapacity] ;}// the construction method public ArrayList () {super () without parameters; // transmits an empty array instance to elementData this. elementData = EMPTY_ELEMENTDATA;} // The constructor for passing in the external set public ArrayList (Collection <? Extends E> c) {// reference elementData = c. toArray (); // update the number of elements in the SET size = elementData. length; // judge the referenced array type, and convert the reference to an Object array to reference if (elementData. getClass ()! = Object []. class) {elementData = Arrays. copyOf (elementData, size, Object []. class );}}

As you can see, the internal storage structure of ArrayList is an array of the Object type, so it can store any type of elements. When constructing an ArrayList, if the initial size is input, it creates an array of objects with the specified capacity. If the initial size is not set, it will not allocate memory space but use an empty array of objects, memory Allocation is performed when elements are actually to be placed. Next let's take a look at its addition, deletion, modification, and query methods.

// Add (add) public boolean add (E e) {// check whether to expand the array before adding. The minimum length of the array is size + 1 ensureCapacityInternal (size + 1 ); // add the element to the end of the array elementData [size ++] = e; return true;} // add (insert) public void add (int index, E element) {// insert position range check rangeCheckForAdd (index); // check whether ensureCapacityInternal (size + 1) needs to be resized; // move the element System after the insert position. arraycopy (elementData, index, elementData, index + 1, size-index); // assign the new value elementData [index] = element; size ++;} to the position to be inserted ;} // Delete public E remove (int index) {// index cannot be greater than size rangeCheck (index); modCount ++; E oldValue = elementData (index ); int numMoved = size-index-1; if (numMoved> 0) {// move the element behind the index to a System. arraycopy (elementData, index + 1, elementData, index, numMoved);} // null reference elementData [-- size] = null; return oldValue ;} // change public E set (int index, E element) {// The index cannot be greater than the size rangeCheck (index); E oldValue = elementData (index ); // replace it with the new element elementData [index] = element; return oldValue;} // check public E get (int index) {// The index cannot be greater than the size rangeCheck (index ); // return elementData (index );}

Each time an element is added to the set, the system first checks whether the capacity is sufficient. Otherwise, the system expands the capacity. The details of the scale-up are described below. Let's take a look at the specific add, delete, modify, and query points to note.
Add: only adds this element to the end. Quick operation.
Increment (insert): The operation is slow because the elements behind the insert position need to be moved and the array replication is involved.
Delete: The operation is slow because you need to move the elements behind the delete position forward and design array replication.
Modify: directly modify the elements at the specified position, which does not involve element movement or array replication.
Query: directly returns the array element of the specified underlying object. This operation is quick.
We can see from the source code that the search and modification are directly directed to the array subscript, which does not involve element movement or array replication. However, insertion and deletion are slow because the elements to be moved involve array replication. Array resizing may also affect the performance of each addition operation. Next, let's take a look at how ArrayList dynamically scales up.

Private void ensureCapacityInternal (int minCapacity) {// if the array is still empty at this time, if (elementData = EMPTY_ELEMENTDATA) {// compare with the default capacity, obtain greater minCapacity = Math. max (DEFAULT_CAPACITY, minCapacity);} // If the array has been initialized, execute this step ensureExplicitCapacity (minCapacity);} private void ensureExplicitCapacity (int minCapacity) {modCount ++; // if the minimum capacity is greater than the array length, the array if (minCapacity-elementData. length> 0) {grow (minCapacity) ;}// maximum private static final int MAX_ARRAY_SIZE = Integer. MAX_VALUE-8; // Add the array length private void grow (int minCapacity) {// obtain the original capacity of the array int oldCapacity = elementData. length; // The capacity of the new array, which is increased by half based on the original int newCapacity = oldCapacity + (oldCapacity> 1 ); // check whether the new capacity is smaller than the minimum capacity. if (newCapacity-minCapacity <0) {newCapacity = minCapacity ;} // check whether the new capacity exceeds the maximum array capacity. if (newCapacity-MAX_ARRAY_SIZE> 0) {newCapacity = hugeCapacity (minCapacity );} // copy the original array to the new array elementData = Arrays. copyOf (elementData, newCapacity );}

Before each element is added, the ensureCapacityInternal method is called to check the set capacity. In this method, check whether the internal array of the current set is an empty array. If yes, create an Object array with the default size of 10. If not, it indicates that the current set has been initialized. Call the ensureExplicitCapacity method to check whether the current array capacity meets the minimum required capacity. If not, call the grow method for resizing. Inside the grow method, we can see that each expansion is to increase the length of the original array by half. expansion is to create an array with a larger capacity and copy all elements of the original array to the new array, then discard the original array and use the new array. So far, we have analyzed the commonly used methods in ArrayList, some of which are worth noting:

1. The underlying implementation of ArrayList is based on arrays. Therefore, it is faster to search for and modify the specified destination, but the deletion and insertion operations are slower.
2. Try to specify the capacity when constructing the ArrayList to reduce the array copy operation when resizing. If you do not know the size, you can assign the value to the default capacity of 10.
3. Check whether expansion is required before each element is added. Each expansion is half of the original capacity.
4. Each time you perform a security check on the underlying object, an exception is thrown immediately if the array is out of bounds.
5. All methods of ArrayList are not synchronized, so it is not thread-safe.
6. The above analysis is based on JDK1.7. Other versions may be different and cannot be generalized.

The above is all the content of this article. I hope it will be helpful for your learning and support for helping customers.

Related Article

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: 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.