ArrayList索引越界

18

如果 ArrayList 的大小已经预定义,为什么会在这个例子中引发 java.lang.IndexOutOfBoundsException?如何解决这个问题?

int size = 2:
ArrayList<Integer[]> nums = new ArrayList<Integer[]>(size);
Integer[] value1 = {1,2,3};
Integer[] value2 = {1,2};
nums.add(1,value1); // java.lang.IndexOutOfBoundsException
nums.add(0,value2);
7个回答

23
你不能在另一个项目设置之前将项目放入ArrayList中。如果你想这样做,你需要首先将第0个位置的项赋值为空。
如果你这样做,它会起作用:
int size = 2:
ArrayList<Integer[]> nums = new ArrayList<Integer[]>(size);
Integer[] value1 = {1,2,3};
Integer[] value2 = {1,2};
nums.add(0, null);
nums.add(1,value1);
nums.set(0,value2);

编辑/使用“set”替换“add”以替换空对象


6
更明确地说,实际上你无法在尚不存在的索引位置插入一个项。 - Dave Newton
5
不是质疑这里的智慧,但是上面解决方案中的第三个add()不会移动内容吗?这样,value1现在不是在索引1上,而是在索引2上了,加入到指定索引处的add()的文档也表明如此。我认为,此后数组内容将为{value2,null,value1}。 - rfeak
索引规则的例外是最后一个索引之后的索引。它并不存在,但您可以在那里添加一个元素来扩展列表。 - Humpity

9
ArrayList构造函数的参数并不是您的代码所假定的列表大小,而是数据结构使用的底层存储的容量
随着向列表中添加元素,容量将根据需要增长。在构造函数中指定初始容量的唯一原因是如果您知道您将要添加大量元素,则预分配一个较大的容量。这意味着当您添加它们时,底层数组不必经常调整大小。
无论您在ArrayList构造函数中指定什么值,列表的大小仅由您放入其中的内容决定,因此您不能在至少添加2个元素之前使用索引为1的index获取该项。

3

3

当你向 ArrayList 添加元素时,列表的长度为0。你不能添加到当前 List 的末尾之外。

我建议这样做:

nums.add(value2);
nums.add(value1); 

为了获得您所期望的订单,请按照以下步骤进行操作。

它对我的情况不适用,因为我可能需要在位置5添加某个元素,下一个在位置2,下一个在位置7等等。 - Klausos Klausos
1
@KlausosKlausos - 听起来你一开始并不需要一个ArrayList。最好先用一个特定大小的普通数组开始,通过索引进行所有插入操作,这样就不必对ArrayList进行任何有趣的操作,然后再将数组放入ArrayList中。此外,请注意,在索引处添加元素会导致现有数组内容的移动。在位置5添加,然后在位置2添加会导致你在5处插入的内容现在变成了6。 - rfeak

1
根据javadoc,当你编写代码时

ArrayList<Integer[]> nums = new ArrayList<Integer[]>(size);

你没有定义nums大小,而是定义了初始容量 - 在这个意义上,ArrayLists不像内置数组(你的代码中的value1value2)。

你可以尝试自己做一下:在每行之后打印nums的大小(为了防止IndexOutOfBoundsException,清理了代码)。

int size = 2:
ArrayList<Integer[]> nums = new ArrayList<Integer[]>(size);
Integer[] value1 = {1,2,3};
Integer[] value2 = {1,2};
System.out.println(nums.size());
nums.add(value2);
System.out.println(nums.size());
nums.add(value1);
System.out.println(nums.size());

这将打印:

0
1
2

0
要得到您想要的结果,您必须编写代码。
nums.add(0, value1);
nums.add(0, value2);

0
为了获得您期望的结果,我建议使用基本类型数组,例如:
Integer[][] nums = new Integer[size][];

然后

Integer[] value1 = {1,2,3};
Integer[] value2 = {1,2};
nums[1] = value1; 
nums[0] = value2;

如果你仍然需要一个ArrayList,只需使用:
new ArrayList<Integer[]>(Arrays.asList(nums));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接