You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确扩容ArrayList?我当前的实现是否为最优方式?

解决归并排序临时ArrayList的IndexOutOfBounds问题

嘿,这个坑我之前写归并排序的时候也踩过,太懂那种突然报越界错误的迷惑感了!

首先得把核心问题说透:你用new ArrayList<>(size)初始化的时候,这里的size是ArrayList的初始容量(capacity),不是它实际存储的元素数量(size)。这时候你的tempArray其实是空的(size=0),调用set(index, ...)自然会抛出IndexOutOfBoundsException——因为set要求索引必须小于当前的元素数量,而不是容量。

你说的“循环执行size次操作来增加数组的size”(比如每次add一个null或默认值),虽然能解决问题,但绝对不是最优方式。下面给你几个更高效简洁的方案:

方案1:用Collections.nCopies直接初始化指定size的ArrayList

可以用Collections.nCopies创建一个包含size个null元素的不可变列表,再传入ArrayList的构造方法:

ArrayList<T> tempArray = new ArrayList<>(Collections.nCopies(size, null));

这样初始化后的tempArray的元素数量直接就是你需要的size,底层数组容量也刚好匹配,之后可以直接用set修改任意索引位置的元素,完全不会有越界问题。这种方式比循环add高效得多,因为它是一次性把所有元素复制到ArrayList的底层数组,不需要循环执行size次add操作。

方案2:直接用泛型数组代替ArrayList

其实归并排序里的临时数组,用原生数组反而更合适——数组访问速度更快,也不会有容量和元素数量混淆的问题。你可以这样创建泛型数组:

T[] tempArray = (T[]) new Object[size];

虽然这里会有类型转换的警告,但这是安全的(我们明确知道这个数组只会存储T类型元素)。之后直接通过tempArray[index] = ...赋值就行,完全不用考虑元素数量的问题,数组长度就是你需要的size。

为什么循环add不是最佳方式?

如果用循环for (int i = 0; i < size; i++) tempArray.add(null);,虽然能把元素数量提升到目标值,但:

  • 代码不够简洁,多了不必要的循环逻辑
  • 哪怕初始容量设为size不会触发扩容,循环执行size次add还是会有额外开销(比如每次add都要检查容量、更新元素数量),不如一次性初始化高效

所以综合来看,方案1或方案2都比循环add要好得多:如果之后需要用到ArrayList的其他方法(比如动态增删)就选方案1;如果只是做临时存储和索引访问,方案2的数组更高效。

内容的提问来源于stack exchange,提问作者Alex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:37:24