当我这样做时
ArrayList<Integer> arr = new ArrayList<Integer>(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的大小,然后立即使用索引,就像数组一样?
答案 0 :(得分:24)
这个怎么样:
ArrayList<Integer> arr = new ArrayList<Integer>(Collections.nCopies(10, 0));
这将使用10个零来初始化arr。然后您可以立即使用索引。
答案 1 :(得分:14)
以下是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
类型为E
的{{1}},在您的情况下:add(1)
),这不会发生。或者,如果它适合您,您可以按照另一个答案中的建议将所有元素初始化为0。
答案 2 :(得分:3)
我认为这里的问题是虽然您已经建议在数组中分配条目空间,但实际上并没有创建条目。
arr.size()
返回什么?
我认为您需要使用add(T)方法。
答案 3 :(得分:2)
想象一个空蛋盒,里面有十个蛋。这或多或少都是你创造的。然后你告诉一个非常精确和令人讨厌的机器人,你用什么告诉他机器人用另一个鸡蛋代替第0个鸡蛋。机器人报告错误。为什么?他无法取代第0个鸡蛋,因为那里没有鸡蛋!有一个可容纳10个鸡蛋的空间,但里面确实没有鸡蛋!
答案 4 :(得分:1)
您可以使用arr.add(1)
,这会在第一个空单元格中添加1
,即0索引的单元格。
或者您可以创建自己的列表:
public static class PresetArrayList<E> extends ArrayList<E> {
private static final long serialVersionUID = 1L;
public PresetArrayList(int initialCapacity) {
super(initialCapacity);
addAll(Collections.nCopies(initialCapacity, (E) null));
}
}
然后:
List<Integer> list = new PresetArrayList<Integer>(5);
list.set(3, 1);
System.out.println(list);
打印:
[null, null, null, 1, null]
答案 5 :(得分:1)
这不是Java特定的答案,而是数据结构的答案。
您将Capacity
概念与Count
(或Size
)概念混淆。
容量就是当你告诉列表预先保留/预分配多个插槽时(在这个ArrayList的情况下,你要说它在' 10 位置的数组) > 内部存储 。发生这种情况时,列表仍然没有任何项目。
大小(或计数)是列表实际拥有的项目数量。在你的代码中,你真的没有添加任何项 - 所以IndexOutOfBoundException是值得的。
答案 6 :(得分:0)
虽然你无法用arraylist做你想做的事,但还有另外一个选择:Arrays.asList()
答案 7 :(得分:0)
容量用于准备ArrayList
以进行扩展。采取循环
List<Integer> list = new ArrayList<>();
for(final int i = 0; i < 1024; ++i) {
list.add(i);
}
list
starts off,容量为10
。因此它内部有一个新的Integer[10]
。当循环添加到列表中时,整数将添加到该数组中。当数组被填充并且添加了另一个数字时,新数组的大小是旧数组的两倍,旧值被复制到新数组。添加项目最多为O(1),最差为O(N)。但添加N个项目将需要约2*1024
个人分配:摊销线性时间。
容量不是大小。如果尚未添加到数组列表中,则大小将为零,并且尝试写入第3个元素将失败。