Java ArrayList IndexOutOfBoundsException尽管给出了初始容量

当我做

ArrayList arr = new ArrayList(10); arr.set(0, 1); 

Java给了我

 Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0 at java.util.ArrayList.rangeCheck(Unknown Source) at java.util.ArrayList.set(Unknown Source) at HelloWorld.main(HelloWorld.java:13) 

有没有一种简单的方法可以预先保留ArrayList的大小,然后立即使用索引,就像数组一样?

这是ArrayList的源代码:

构造函数:

 public ArrayList(int initialCapacity) { super(); if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); this.elementData = new Object[initialCapacity]; } 

你调用了set(int, E)

 public E set(int index, E element) { rangeCheck(index); E oldValue = elementData(index); elementData[index] = element; return oldValue; } 

Set调用rangeCheck(int)

 private void rangeCheck(int index) { if (index >= size) { throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } } 

它可能很微妙,但是当您调用构造函数时,尽管初始化了Object[] ,但您没有初始化size 。 因此,从rangeCheck ,您得到IndexOutOfBoundsException ,因为size是0.而不是使用set(int, E) ,您可以使用add(E e) (在您的情况下,将e类型添加到列表的末尾: add(1) ),这不会发生。 或者,如果它适合您,您可以按照另一个答案中的建议将所有元素初始化为0。

这个怎么样:

 ArrayList arr = new ArrayList(Collections.nCopies(10, 0)); 

这将使用10个零来初始化arr。 然后您可以立即使用索引。

我相信这里的问题是虽然你已经建议在数组中分配条目空间,但你实际上并没有创建条目。

arr.size()返回什么?

我认为你需要使用add(T)方法。

除了编程之外,你在这里尝试做的事情是不合逻辑的。

想象一个空蛋盒,里面有十个蛋。 这或多或少都是你创造的。 然后你告诉一个超级精确和烦人的,你告诉他的机器人用另一个鸡蛋代替第0个鸡蛋。 机器人报告错误。 为什么? 他无法取代第0个鸡蛋,因为那里没有鸡蛋! 有一个可容纳10个鸡蛋的空间,但里面真的没有鸡蛋!

您可以使用arr.add(1) ,它将在第一个空单元格中添加1 ,即0索引的单元格。

或者您可以创建自己的列表:

 public static class PresetArrayList extends ArrayList { private static final long serialVersionUID = 1L; public PresetArrayList(int initialCapacity) { super(initialCapacity); addAll(Collections.nCopies(initialCapacity, (E) null)); } } 

然后:

 List list = new PresetArrayList(5); list.set(3, 1); System.out.println(list); 

打印:

 [null, null, null, 1, null] 

这不是Java特定的答案,而是数据结构的答案。

您将Capacity概念与Count (或Size )混淆。

容量是当你告诉列表预先保留/预分配多个插槽(在这个ArrayList的情况下,你说它创建一个10个位置的数组)在它的’ 内部存储器中 。 发生这种情况时,列表仍然没有任何项目。

大小(或计数)是列表实际具有的项目数量。 在您的代码中,您确实没有添加任何项 – 因此IndexOutOfBoundException是值得的。

虽然你不能用arraylist做你想做的事,但还有另一种选择:Arrays.asList()

容量用于准备ArrayList以进行扩展。 循环

 List list = new ArrayList<>(); for(final int i = 0; i < 1024; ++i) { list.add(i); } 

list 以容量10 。 因此它内部有一个新的Integer[10] 。 当循环添加到列表中时,整数将添加到该数组中。 当数组被填充并且添加了另一个数字时,新数组的大小是旧数组的两倍,旧值将被复制到新数组。 添加项目最多为O(1),最差为O(N)。 但添加N个项目将需要大约2*1024个人分配:摊销线性时间。

容量不是大小。 如果尚未添加到数组列表中,则大小将为零,并且尝试写入第3个元素将失败。