java arraylist ensureCapacity无法正常工作

要么我做错了,要么我不理解这种方法是如何工作的。

ArrayList a = new ArrayList(); a.ensureCapacity(200); a.add(190,"test"); System.out.println(a.get(190).toString()); 

我原以为ensureCapacity会让我插入一个索引最多的记录。 有没有不同的方法来做到这一点?

我在第三行得到一个IndexOutOfBounds错误。

不, ensureCapacity不会更改ArrayList逻辑大小 – 它会更改容量 ,即列表在下次需要复制值之前可以达到的大小。

您需要非常了解逻辑大小(即范围[0, size)中的所有值都可访问,并且添加新元素将以索引size添加它)和容量更多的实现之间的差异细节真的 – 它是用于存储的后备arrays的大小。

调用ensureCapacity应该只在性能方面做出任何改变(通过避免过度复制) – 如果你看到我的意思,它不会影响列表中的内容的逻辑模型。

编辑:听起来你想要一种ensureSize()方法,它可能看起来像这样:

 public static void ensureSize(ArrayList list, int size) { // Prevent excessive copying while we're adding list.ensureCapacity(size); while (list.size() < size) { list.add(null); } } 

确保容量不会将项目添加到列表中。 如果已经添加了191个元素,则只能获取元素190或添加元素190。 “容量”只是ArrayList在需要调整其内部数据结构(数组)大小之前可以容纳的对象数。 如果ArrayList有一个getCapacity(),那么这样做:

 ArrayList a = new ArrayList(); a.ensureCapacity(200); System.out.println(a.size()); System.out.println(a.getCapacity()); 

将分别打印出0和大于或等于200的某个数字

因此,正如其他人提到的那样, ensureCapacity并非如此。 看起来你想从一个200个空的ArrayList开始? 那么这将是最简单的方法:

 ArrayList a = new ArrayList(Arrays.asList( new String[200] )); 

然后,如果你想用“test” 替换元素190,请执行以下操作:

 a.set(190, "test"); 

这不同于

 a.add(190, "test"); 

这将在索引190中添加“test”并将其他9个元素向上移动,从而生成201的大小列表。

如果你知道你总是要有200个元素,那么使用数组可能会更好。

ArrayList将其容量(内部数组的大小)与其大小(添加的元素数)分开维护,“set”方法取决于已经分配给元素的索引。 没有办法设置大小。 如果需要,可以添加带循环的虚拟元素:

 for (int i = 200; --i >= 0;) a.add(null); 

JavaDoc再一次澄清了这种情况:

 Throws: IndexOutOfBoundsException - if index is out of range (index < 0 || index > size()). 

请注意, size()返回List当前持有的元素数。

ensureCapacity只是确保底层数组的容量大于或等于参数。 它不会更改ArrayList的大小。 它不会通过API显示任何更改,因此除了在ArrayList调整其内部数组大小之前可能会更长时间之外,您不会注意到差异。

向ArrayList添加190个空条目会导致滥用数据结构。

  1. 考虑使用标准原始数组。

  2. 如果您需要generics或想要更有效地使用空间,那么考虑SparseArray甚至像HashMap这样的Map可能适合您的目的。

  public static void fillArrayList(ArrayList arrayList, long size) { for (int i = 0; i < size + 1; i++) { arrayList.add(i,"-1"); } } public static void main(String[] args) throws Exception { ArrayList a = new ArrayList(10); fillArrayList(a, 190); a.add(190,"test"); System.out.println(a.get(190).toString()); }