返回

ArrayList源码的深入剖析

后端

导言

ArrayList是Java集合框架中最常用的动态数组实现之一。它是一个可变大小的数组,随着元素的添加或删除而自动调整大小。深入理解ArrayList的源码可以帮助我们掌握其内部运作机制,并优化其使用。

字段

ArrayList有以下主要字段:

  • elementData:一个Object类型的数组,用于存储ArrayList中的元素。
  • size:ArrayList中元素的实际数量。
  • modCount:修改计数器,用于检测并发的修改。

构造器

ArrayList提供了多个构造器,用于创建具有不同初始容量或初始元素的ArrayList实例。以下是两个最常用的构造器:

public ArrayList() {
    this(10); // 默认初始容量为10
}

public ArrayList(int initialCapacity) {
    if (initialCapacity > 0) {
        elementData = new Object[initialCapacity];
    } else if (initialCapacity == 0) {
        elementData = EMPTY_ELEMENTDATA;
    } else {
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    }
}

扩容流程

当ArrayList中的元素数量达到其容量时,需要进行扩容。扩容流程通常如下:

  1. 创建一个新数组,容量为当前容量的1.5倍(默认情况下)。
  2. 将当前元素从旧数组复制到新数组。
  3. 将elementData引用指向新数组。

以下是add方法的扩容流程:

public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // 检查是否需要扩容
    elementData[size++] = e;
    return true;
}

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

    if (size >= minCapacity) {
        int newCapacity = size + (size >> 1);  // 扩容为当前容量的1.5倍
        if (newCapacity - minCapacity <= 0) {
            newCapacity = minCapacity;
        }
        if (newCapacity - MAX_ARRAY_SIZE > 0) {
            newCapacity = hugeCapacity(minCapacity);
        }

        // 创建新数组并复制元素
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
}

结论

通过对ArrayList源码的分析,我们可以深入了解其内部运作机制,包括字段、构造器和扩容流程。这些知识可以帮助我们优化ArrayList的使用,避免内存浪费和性能问题。