In-depth understanding of the dynamic expansion mechanism and application of ArrayList

In java programming, data structures play a vital role, and ArrayList, as a commonly used dynamic array, provides us with convenience when processing data. Among them, its unique dynamic expansion mechanism has won it a wide range of applications. Whether we are at work or in interviews, we will encounter ArrayList. This article will deeply explore the dynamic expansion mechanism of ArrayList so that we can use it at work or in interviews.

Introduction to ArrayList

ArrayList is a class in the Java programming language. It implements the List interface and stores elements in an array at the bottom. Provides functions such as adding (add), deleting (remove), and getting elements (get) to List. The disadvantage is that elements must be stored continuously, so addition and deletion are slow, but the advantage is that querying is fast. ArrayList has dynamic expansion characteristics, which means that it can automatically adjust the size of the internal array as needed to accommodate different numbers of elements.

Detailed explanation of dynamic expansion

When we add elements to the ArrayList (call add() or addAll()), a ensureCapacityInternal()method is called

Let’s look at the source code:

add()

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

addAll()

public boolean addAll(Collection<? 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;
}

As can be seen from the source code, both methods call ensureCapacityInternal()this method. The parameters are the length of the current list plus the number of objects to be inserted (1 for a single object, and the length of the collection for a collection of objects), which is a collection. Minimum length required to add element

ensureCapacityInternal()

private void ensureCapacityInternal(int minCapacity) {
    
    
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}

ensureExplicitCapacity()The input parameters of the method are calculateCapacity()(the parameters are the array that stores the actual elements and the minimum length required to add elements to the collection) and the value processed by the method.

calculateCapacity()

private static int calculateCapacity(Object[] elementData, int minCapacity) {
    
    
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
    
    
        return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    return minCapacity;
}

The value returned by the current method is if the source collection is empty, the default capacity (10) is compared with the minimum length value required to add elements to the element collection, whichever is larger. If it is not empty, minCapacity is returned.

_20230828230112.png

ensureExplicitCapacity()

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

    // overflow-conscious code
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

grow

private void grow(int minCapacity) {
    
    
    // overflow-conscious 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, so this is a win:
    elementData = Arrays.copyOf(elementData, newCapacity);
}

Let’s explain this code in detail

  • int oldCapacity = elementData.length;

Get the capacity of the current array, which is the length of the elementData array, which is the length of the array currently storing elements.

  • int newCapacity = oldCapacity + (oldCapacity >> 1);

Calculate new capacity. Here, bit operation is used to shift right by 1 bit (equivalent to dividing by 2) to expand the current capacity by 1.5 times.
If >>you don’t know much about the bitwise operator, you can read our previous article.深入解析Java中的位运算符:<<、>>和>>>

  • if (newCapacity - minCapacity < 0)

Check whether the calculated new capacity meets the minimum capacity requirements. If it is not satisfied, the new capacity is set to the minimum capacity minCapacity.

  • if (newCapacity - MAX_ARRAY_SIZE > 0)

Check whether the new capacity exceeds the maximum array capacity limit. MAX_ARRAY_SIZE is a constant defined internally in ArrayList, indicating the maximum capacity of the array. If the new capacity exceeds this limit, call the hugeCapacity(minCapacity) method to obtain a large enough capacity.

_20230828230251.png

_20230828230304.png

  • elementData = Arrays.copyOf(elementData, newCapacity);

Use the Arrays.copyOf() method to copy the original elementData array to a new array. The capacity of the new array is the calculated new capacity newCapacity. This implements the actual array expansion operation.

Usage precautions and optimization

  • initial size

When creating an ArrayList, if we can predict the approximate amount of data, initializing an appropriate initial size can reduce the number of expansions and thus improve performance.

  • Avoid frequent expansion

Frequent expansion will bring large performance overhead, so try to avoid adding elements multiple times in the loop to avoid triggering multiple expansion operations.

Summarize

As a commonly used data structure, ArrayList brings great convenience to our programming work with the support of dynamic expansion mechanism. An in-depth understanding of its dynamic expansion principles and application scenarios will help us better use ArrayList at work, and can also demonstrate solid basic knowledge in interviews.

Whether you are dealing with business logic with an uncertain amount of data or answering questions related to ArrayList in a technical interview, understanding its dynamic expansion mechanism will allow you to deal with various challenges more calmly.

Guess you like

Origin blog.csdn.net/weixin_44002151/article/details/132550370