2010-05-09 66 views
5

我遇到了问题ArrayList。我需要它来存储结果。因为我想从元素n开始,所以我试图给ArrayList一个容量ensureCapacity(n+1)来使用set(n,x),但我得到一个IndexOutOfBoundsExceptionJava ArrayList <Double> IndexOutOfBoundsException问题

我试图存储n add(x)之前使用设置和这个工程。

所以我想知道为什么它不会对我的工作方式,以及如何解决这个问题,因为放了N次一add(x)是不是一个很好的风格;-)

回答

6

如果你不喜欢使用自己的循环和列表add方法直接再有另一种方式。创建ArrayList与元素的数量要直接这样说:

final int MAX_ELEMENTS = 1000; 
List<Integer> myList = new ArrayList<Integer>(
    Collections.<Integer>nCopies(MAX_ELEMENTS, null)); 

或者,如果你已经拥有你想要n元素来扩大规模的列表:

myList.addAll(Collections.<Integer>nCopies(n, null)); 

(注意,我在这里假定该列表将持有Integer对象,但您可以将其更改为您的自定义类型。如果您正在使用原始/预Java 5类型,那么只需删除通用声明。)

至于您的实际问题:容量!=内容。 ArrayList内部有一个物理数组和一个实际内存数。增加容量,改变内部数组,因此它可以容纳许多元素,但是,计数不会改变。你需要添加元素来增加这个数量。另一方面,如果你只是想设置特定的元素并知道你想要使用的最大值,为什么不直接使用数组呢?为什么不直接使用数组呢?为什么不直接使用数组呢?为什么不直接使用数组呢?为什么不直接使用数组呢?为什么不直接使用数组呢?如果您需要将此数组传递给需要List的API,则请使用Arrays.asList。其他类仍然可以更改后备数组的内容,但无法增加其大小或容量。

7

当你改变的能力一个ArrayList它不会创建任何元素,它只是在可能存在元素的地方保留内存。您可以在调整容量之前和之后检查大小,并且您会看到它不会更改。

更改容量的目的是,如果您事先知道您将拥有多少元素,那么您可以在添加新元素时避免不必要的重复调整大小,并且可以避免过量未使用容量造成的内存浪费。

0

您收到此异常,因为的ensureCapacity()只可以确保有分配将对象添加到一个ArrayList足够的内存,我相信这是如果你想添加一次多个对象,而不必重新定位记忆。

做你想要你就必须启动与null元素第一ArrayList的是什么...

int n = 10; //capacity required 
ArrayList foo = new ArrayList(); 

for(int i=0; i<=n; i++) { 
     foo.add(null); 
} 

然后,你必须在对象列表,你可以通过索引引用和你不会收到异常。

0

ensureCapacity()有另一个目的。它应该用于在构建完成后知道List所需的大小的情况。如果您在构造函数之前知道大小,只需将其作为参数传递给构造函数即可。

在前一种情况下,使用ensureCapacity()可在每次​​添加时保存多个备份数组的副本。然而,使用这种方法离开结构在一个表面上不一致的状态

  • 背衬阵列的尺寸增加在ArrayList
  • size字段不是。

然而,这是正常的,因为容量=大小

使用add(..)方法,这是增加size领域唯一的一个!

ArrayList list = new ArrayList(); 
list.ensureCapacity(5); // this can be done with constructing new ArrayList(5) 

for (int i = 0; i < list.size - 1; i ++) { 
    list.add(null); 
} 
list.add(yourObject); 
0

也许你应该重新考虑使用List<Double>的选择。如果要按奇数顺序添加元素,那么Map<Integer,Double>可能更合适。

这是否合适取决于有关您的使用情况的知识,但目前我没有这方面的知识。

数据结构最终会被完全填充还是数据稀疏?

+0

这将是最干净的解决方案,但ArrayList被用作仅使用ArrayList的方法中的参数。也许如果我有足够的时间,我会超载使用Map insted。 – 2010-05-09 18:28:52

+1

您可能还会考虑加载一个Map,然后编写一个方法,在加载后从地图内容构建一个ArrayList。 但是,如果你真的需要一个ArrayList,Bozho发布的解决方案可能会很好。 – 2010-05-09 19:05:01

+0

“该ArrayList被用作只有ArrayList的方法中的参数”严重吗?那里有代码需要'ArrayList'而不是'List'? – Powerlord 2010-05-10 18:54:36

0

别人说过的ensureCapacity()什么...

你应该写这样DynamicArrayList一类扩展的ArrayList。那么只需重写add(n,x)就可以执行指定的循环add(null)逻辑。

2

正如其他人所回答的那样,ensureCapacity()只是与性能有关,并不是常用的常用用户。

布鲁斯Eckel的在Java中书思考:

在悄悄话,约书亚布洛赫 写道:” ......我相信,我们犯了错误通过 允许实现细节(例如 如哈希表尺寸和负荷因子) 到我们的API。客户应 或许告诉我们预期的最​​大 大小的集合,我们应该 把它从那里,客户可以轻松 做弊大于利通过选择 这些参数的值。作为 极端示例,请考虑Vector的 capacityIncrement。没有人应该 设置这个,我们不应该有 提供它。如果将其设置为任何 非零值,则 的附加序列的渐近代价从线性 变为二次。换句话说,它 破坏你的表现。随着时间的推移, 我们开始明智地讨论这种事情。如果你看一下 IdentityHashMap,你会发现它 没有低级别的调整参数”