
本文详解IndexOutOfBoundsException在空ArrayList上调用set()时的根本原因,并提供安全、高效的替代实现,强调add()与set()的本质区别及预分配容量的最佳实践。
本文详解`indexoutofboundsexception`在空arraylist上调用`set()`时的根本原因,并提供安全、高效的替代实现,强调`add()`与`set()`的本质区别及预分配容量的最佳实践。
在Java中,ArrayList.set(int index, E element) 方法不会扩展列表长度,它仅用于替换已有索引位置上的元素。当ArrayList为空(即size() == 0)时,任何索引(包括0)都是非法的——这正是报错 java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0 的根本原因。
在原始代码中:
List<Boolean> res = new ArrayList<Boolean>(candies.length); // 仅预分配内部数组容量,size仍为0 res.set(i, true); // ❌ 错误:i=0时试图设置第0个元素,但列表当前无任何元素
尽管通过构造函数指定了初始容量(candies.length),这只是优化了底层Object[]数组的大小,并未改变列表逻辑长度(size)。此时调用set()等同于对一个空容器进行“越界写入”。
✅ 正确做法是使用 add() 方法逐个追加元素:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
public List<Boolean> kidsWithCandies(int[] candies, int extraCandies) {
if (candies == null || candies.length == 0) {
return new ArrayList<>(); // 边界防护:空输入返回空列表
}
// 一次排序 + 提前计算阈值,避免重复比较
Arrays.sort(candies);
int threshold = candies[candies.length - 1] - extraCandies;
List<Boolean> res = new ArrayList<>(candies.length); // 预分配容量提升性能
for (int candy : candies) {
res.add(candy >= threshold); // ✅ 使用add()安全插入
}
return res;
}⚠️ 注意事项:
-
set()vsadd():set()要求索引0 ≤ index ;<code>add()始终在末尾追加,自动维护size。 -
预分配容量 ≠ 初始化元素:
new ArrayList(n)仅减少扩容次数,不生成默认元素。 -
边界防御:务必检查输入数组是否为
null或空,避免ArrayIndexOutOfBoundsException(如candies[candies.length-1]在空数组下崩溃)。 -
语义优化:原逻辑中
candies[i] + extraCandies > max等价于candies[i] > max - extraCandies,提前计算threshold更清晰且避免循环内重复减法。
该方案时间复杂度为 O(n log n)(主要由排序决定),空间复杂度 O(n),符合题意且健壮可靠。

















