我可能做错了,或者我不理解这个方法是如何工作的。
ArrayList<String> a = new ArrayList<String>();
a.ensureCapacity(200);
a.add(190,"test");
System.out.println(a.get(190).toString());
我原本认为ensureCapacity会让我插入一个索引值高达那个容量的记录。还有其他方法可以实现这个吗?
第三行代码出现了IndexOutOfBounds错误。
ensureCapacity
并不会改变一个ArrayList
的逻辑大小(logical size),它只会改变容量(capacity),也就是列表在下次需要复制值之前可以达到的大小。[0, size)
内的值都是可访问的,并且添加新元素会将其添加到索引size
处。而容量更像是实现细节——它是用于存储的后备数组的大小。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);
}
}
正如其他人提到的那样,ensureCapacity
不是用于这个目的的。看起来你想要从 200 个空值开始使用 ArrayList
? 那么这是最简单的方法:
ArrayList<String> a = new ArrayList<String>(Arrays.asList( new String[200] ));
如果你想用"test"替换元素190,则可以执行以下操作:
a.set(190, "test");
这与
之前的不同。a.add(190, "test");
这将在索引190处添加“test”,并将其他9个元素向上移动,导致列表大小为201。
如果您知道始终会有200个元素,最好使用数组。
确保容量不是向列表中添加项目。只有在已经添加了191个元素后,才能获取第190个元素或在第190个元素处添加元素。 "容量"只是ArrayList在需要调整其内部数据结构(数组)大小之前可以容纳的对象数量。如果ArrayList具有getCapacity()方法,则可以执行以下操作:
ArrayList<String> a = new ArrayList<String>();
a.ensureCapacity(200);
System.out.println(a.size());
System.out.println(a.getCapacity());
分别会打印出0和大于等于200的某个数字
ArrayList将其容量(内部数组的大小)与其大小(添加的元素数量)分别维护,而“set”方法依赖于索引已分配给元素。没有设置大小的方法。如果您需要这样做,可以使用循环添加虚拟元素:
for (int i = 200; --i >= 0;) a.add(null);
public static void fillArrayList(ArrayList<String> arrayList, long size) {
for (int i = 0; i < size + 1; i++) {
arrayList.add(i,"-1");
}
}
public static void main(String[] args) throws Exception {
ArrayList<String> a = new ArrayList<String>(10);
fillArrayList(a, 190);
a.add(190,"test");
System.out.println(a.get(190).toString());
}
向 ArrayList 添加 190 个空条目似乎是对数据结构的误用。
考虑使用标准基本数组。
如果您需要泛型或想要更有效地使用空间,则可以考虑使用 SparseArray
或甚至像 HashMap
这样的 Map
可能适合您的目的。
再次使用JavaDoc来澄清情况:
Throws: IndexOutOfBoundsException
- if index is out of range (index < 0 || index > size()).
size()
返回列表当前持有的元素数量。ensureCapacity
只是确保底层数组的容量大于或等于参数。它不会改变 ArrayList
的大小。它不会通过 API 显示任何更改,因此您不会注意到任何差异,除了在 ArrayList
调整其内部数组之前可能需要更长的时间。