返回

揭秘ArrayList 源代码:动态数组背后的秘密

后端

揭秘 Java 中ArrayList 的神奇扩容机制

在计算机的世界中,数据结构就像一本神奇的书,它存储着各种各样的信息。今天,我们将深入研究 Java 中的 ArrayList,它就像一个伸缩自如的口袋,能够根据需要自动调整大小,随时容纳新的元素。

什么是 ArrayList?

ArrayList 是一种动态数组,这意味着它可以在运行时根据需要自动调整大小。与普通数组不同,ArrayList 不需要指定固定的长度。它会自动增长和缩小,以适应存储元素的数量。

ArrayList 的核心源码

要深入了解 ArrayList 的工作原理,让我们来看看它的核心源码:

private Object[] elementData; // 数组
private int size; // 大小
private static final int DEFAULT_CAPACITY = 10; // 默认容量

public boolean add(E e) {
    if (size == elementData.length) {
        grow(); // 扩容
    }
    elementData[size++] = e;
    return true;
}

private void grow() {
    int newCapacity = elementData.length * 3 / 2 + 1; // 新容量
    Object[] newArray = new Object[newCapacity]; // 新数组
    System.arraycopy(elementData, 0, newArray, 0, size); // 复制原数组元素
    elementData = newArray; // 指向新数组
}

ArrayList 的扩容机制

当 ArrayList 中的容量不足以容纳更多元素时,它会自动调用 grow() 方法来扩容。这个方法会创建一个新数组,其容量为原数组容量的 1.5 倍再加 1。

随后,方法会将原数组中的元素复制到新数组中,并更新数组的引用指向新数组。这样,ArrayList 就可以容纳更多的元素了。

一个实际例子

假设我们有一个初始容量为 10 的 ArrayList。当我们添加第一个元素时,ArrayList 会创建一个容量为 10 的数组。

随着我们继续添加元素,当数组容量不足时,ArrayList 会调用 grow() 方法来扩容。假设我们在第 11 个元素处触发了扩容机制,数组容量将增加到 15(10 * 1.5 + 1 = 15)。

同样,当我们在第 16 个元素处触发扩容时,数组容量将增加到 23(15 * 1.5 + 1 = 23),以此类推。

ArrayList 中的关键变量

在 ArrayList 的源码中,有几个关键变量值得注意:

  • elementData: 这是 ArrayList 的核心,它是一个数组,存储着实际的数据元素。
  • size: 表示 ArrayList 中实际存储的元素数量。
  • DEFAULT_CAPACITY: ArrayList 创建时的默认容量,默认为 10。

总结

ArrayList 的扩容机制是一个巧妙的解决方案,它允许 ArrayList 根据需要动态调整大小。这使得 ArrayList 成为处理具有可变长度数据集合的理想选择。通过理解其背后的机制,我们可以更有效地利用 ArrayList 的强大功能。

常见问题解答

1. ArrayList 是如何跟踪元素的?

ArrayList 使用一个名为 elementData 的数组来存储元素。elementData 数组的索引对应于 ArrayList 中元素的索引。

2. ArrayList 的容量和大小有什么区别?

ArrayList 的容量是数组可以容纳的最大元素数量,而大小是数组中实际存储的元素数量。

3. ArrayList 何时扩容?

当数组容量不足以容纳另一个元素时,ArrayList 就会扩容。

4. ArrayList 扩容后,元素的顺序会改变吗?

不会。当 ArrayList 扩容时,元素的顺序保持不变。

5. ArrayList 的扩容效率如何?

ArrayList 的扩容是一个 O(n) 操作,其中 n 是 ArrayList 中的元素数量。这意味着扩容的时间随 ArrayList 中元素数量的增加而增加。