ArrayList的 `add` 方法与 `addAll` 方法的实现原理

170 阅读3分钟

ArrayList 简述

ArrayList 是 Java 集合框架中的一个类,它实现了 List 接口,内部通过一个可增长的数组来存储元素。ArrayList 提供了丰富的操作接口,包括添加、删除、查找等。其中,add 方法和 addAll 方法是向 ArrayList 中添加元素的主要方式。

add(E e) 方法的实现原理

add(E e) 方法用于向 ArrayList 的末尾添加一个元素。其实现原理大致如下:

  1. 检查容量:首先,ArrayList 会检查当前内部数组的容量是否足够添加新元素。如果当前元素数量(size)等于数组容量(elementData.length),则需要进行扩容操作。
  2. 扩容操作:如果需要扩容,ArrayList 会计算出一个新的容量(通常是原容量的1.5倍,具体实现可能略有不同),然后创建一个新的数组,并将原数组中的元素复制到新数组中。扩容操作是通过调用 ensureCapacityInternal(int minCapacity) 方法实现的,该方法最终会调用 grow(int minCapacity) 方法来完成扩容和元素复制。
  3. 添加元素:在确认容量足够后,ArrayList 会将新元素添加到内部数组的末尾,并更新 size 属性以反映新的元素数量。
addAll(Collection<? extends E> c) 方法的实现原理

addAll(Collection<? extends E> c) 方法用于将指定集合中的所有元素添加到 ArrayList 的末尾。其实现原理与 add(E e) 方法类似,但处理的是集合而非单个元素:

  1. 检查容量:首先,ArrayList 会计算要添加的集合的大小,并与当前元素数量相加,以检查是否需要扩容。如果需要的总容量超过了当前数组的容量,则进行扩容操作。
  2. 扩容操作(如果需要):扩容操作与 add(E e) 方法中的扩容相同,即创建一个新的数组,并将原数组中的元素复制到新数组中。
  3. 添加集合元素:在确认容量足够后,ArrayList 会遍历指定的集合,并将集合中的每个元素依次添加到内部数组的末尾。这通常是通过 System.arraycopy() 方法或类似的高效复制机制实现的,以减少复制操作的开销。
  4. 更新 size:最后,ArrayList 会更新其 size 属性,以反映新添加的元素数量。
注意事项
  • 在进行扩容操作时,ArrayList 会创建一个新的数组,这可能会导致原数组中的元素在短时间内被复制两次(一次是扩容,一次是添加新元素),因此,在元素数量非常大时,这可能会成为性能瓶颈。
  • 尽管 ArrayList 的自动扩容机制提供了极大的灵活性,但在某些场景下(如已知元素数量大致范围),手动设置初始容量可以减少扩容次数,从而提高性能。
  • addAll 方法在处理大型集合时,如果集合中的元素数量接近或超过当前 ArrayList 的容量,则可能导致多次扩容操作,这会影响性能。因此,在可能的情况下,应先检查集合大小,并考虑是否需要预先扩容。