Data Structure and Algorithms - Array - Java ArrayList Source Analysis - Completed Today

Posted by Nukedesign on Fri, 23 Aug 2019 11:21:31 +0200

The links to this article are as follows:

1. Overview

  • At the bottom of the ArrayList is an array, which is equivalent to a dynamic array. Compared with arrays in Java, its capacity can grow dynamically. Before adding a large number of elements, the application can use the ensureCapacity operation to increase the capacity of the ArrayList instance. This can reduce the number of incremental redistributions.
  • It inherits from AbstractList and implements List, Random Access, Cloneable, java.io.Serializable interfaces.
  • ArrayList inherits AbstractList and implements List. It provides functions of adding, deleting, modifying and traversing.
  • ArrayList implements the Random Access interface, which is a flag interface, indicating that the List collection that implements this interface supports fast random access. In ArrayList, we can quickly get the element object by its ordinal number, which is fast random access.
  • ArrayList implements the Cloneable interface, which covers the function clone() and can be cloned.
  • ArrayList implements the java.io.Serializable interface, and Serializable is a flag interface, which means that ArrayList supports serialization and can be transmitted through serialization.
  • Unlike Vector, operations in ArrayList are not thread-safe! Therefore, it is recommended to use ArrayList only in a single thread, while Vector or CopyOnWriteArrayList can be selected in a multi-thread.
    • For a detailed introduction to thread insecurity in ArrayList, see my other blog:

2. Comparison of JDK 1.7 and JDK 1.8

JDK1.7

package java.util;

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
    private static final long serialVersionUID = 8683452581122892189L;

    private transient Object[] elementData;

    private int size;

    public ArrayList(int initialCapacity) {
        super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        this.elementData = new Object[initialCapacity];
    }

    public ArrayList() {
        this(10);
    }

}
  • ArrayList list =new ArrayList();
  • Call this(10), that is, this.elementData = new Object[10], when you create an array using the default constructor; that is, create an object [] array elementData of 10 length.

JDK1.8

package java.util;

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
    //Serialized version
    private static final long serialVersionUID = 8683452581122892189L;
    //The default length of the array to be created
    private static final int DEFAULT_CAPACITY = 10;
    //Initialize an empty array
    private static final Object[] EMPTY_ELEMENTDATA = {};
    
    transient Object[] elementData; // non-private to simplify nested class access
    //Number of elements in an array
    private int size;
    //Parametric structure
    public ArrayList(int initialCapacity) {
        super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        this.elementData = new Object[initialCapacity];
    }
    //Parametric structure
    public ArrayList() {
        super();
        this.elementData = EMPTY_ELEMENTDATA;
    }

    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

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

    private void ensureCapacityInternal(int minCapacity) {
        if (elementData == EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }

   private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
    
    private void grow(int minCapacity) {
        
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
}
  • ArrayList list =new ArrayList();
  • When the default constructor is called, the underlying Object[] elementData is initialized to {} without creating an array of 10 lengths.
  • list.add(123);
  • That is, when the first add is added, an array of 10 lengths is created and element 123 is added to the array.

Summary:

  • The default creation of ArrayList objects in JDK 1.7 is similar to that of hungry Chinese in singleton mode, and the default creation of ArrayList objects in JDK 1.8 is similar to that of lazy Chinese in singleton mode, delaying the creation of arrays and saving memory.

3. Detailed analysis of source code

The following profiling version is JDK 1.8

 

 

 

 

4. Emphasis analysis

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Topics: Programming Java JDK