ewArrayListWithExpectedSize
并不是 ArrayList
的标准 API,而是一个自定义的工具方法,它通常用于创建一个具有预估大小的 ArrayList
。通过预设一个适当的初始容量,可以减少或避免 ArrayList
在插入元素时的扩容。这个方法本质上是使用 ArrayList(int initialCapacity)
构造函数,设置初始容量,但在内部加入了一些优化,比如考虑适当的额外空间。
从你的代码中,newArrayListWithExpectedSize
调用的方式是这样的:
public static <E> ArrayList<E> newArrayListWithExpectedSize(int estimatedSize) { return new ArrayList<>(computeArrayListCapacity(estimatedSize)); }
1. 如何扩容?
ArrayList
扩容的机制是当当前的容量不足以存放新的元素时,它会创建一个新的更大的数组来容纳更多的元素。具体的扩容策略是:
- 初始时,
ArrayList
会分配一个空数组并设置初始容量(例如:new ArrayList<>(10)
会创建一个初始容量为 10 的数组)。 - 当插入元素时,如果数组满了,
ArrayList
会扩容,通常是 1.5 倍的增长方式。例如:如果当前容量为 10,扩容后会变为 15。 - 扩容后,原数组中的元素会被复制到新的、更大的数组中。
2. computeArrayListCapacity
的作用:
computeArrayListCapacity
是一个用于计算合理初始容量的工具方法,目的是避免无谓的扩容。它返回一个计算后的容量值,通常会比预估的大小大一些,以便处理超出预期的情况。
static int computeArrayListCapacity(int arraySize) { checkNonnegative(arraySize, "arraySize"); return IntUtils.saturatedCast(5L + arraySize + (arraySize / 10)); }
例如,如果 arraySize
是 1000,计算后的容量可能是 1100(基于公式 5 + arraySize + (arraySize / 10)
)。这不仅能满足存储预估数量的需求,还能留有一些额外空间,避免很快就需要扩容。
3. 如何扩容与 newArrayListWithExpectedSize
相关?
newArrayListWithExpectedSize(saveSize)
的作用是根据你传入的 saveSize
(预计保存的元素数量)计算合适的初始容量,并创建一个具有这个容量的 ArrayList
。例如,如果预计需要存储 1000 个元素,调用这个方法会创建一个初始容量适中的 ArrayList
,并根据实际需求进行适当的扩容。
而在插入元素时,如果数据超过了当前容量,ArrayList
仍然会进行扩容操作,通常按照 1.5 倍的方式增加容量,直到足够存储所有元素。
4. 扩容的优势:
使用 newArrayListWithExpectedSize
预估容量的主要优势是:
- 减少扩容次数:由于容量设置接近实际需要的大小,
ArrayList
不会频繁扩容,从而提高性能。 - 内存管理优化:避免了过早或过多的内存分配,避免浪费内存,也避免了频繁的内存复制操作。
- 适应性强:通过预估数据量并略微增加容量,可以在数据量超出预期时依然能够容纳所有数据,避免因扩容过快导致的性能下降。
总结:
newArrayListWithExpectedSize
的作用是根据预估的元素数量计算并分配一个适当大小的初始容量,从而减少 ArrayList
在插入数据时的扩容次数。在扩容时,ArrayList
会根据内部逻辑自动扩展容量,通常按照 1.5 倍的增长方式,而预先计算并设置容量有助于提高内存使用效率并减少不必要的性能开销。