Java ArrayListIndexOutOfBoundsException 问题

发布于 2024-08-31 20:50:52 字数 346 浏览 4 评论 0原文

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

我尝试在使用 set 之前存储 n add(x) ,这有效。

所以我想知道为什么它在我的方式上不起作用以及如何解决这个问题,因为 put n 次 add(x) 不是一个好的风格;-)

I've got a Problem with ArrayList. I need it to store a result. Because I want to start with element n I tried to give the ArrayList a capacity with ensureCapacity(n+1) to use set(n,x) but I get an IndexOutOfBoundsException.

I tried to store n add(x) before the use of set and this works.

So I'd like to know why it doesn't work on my way and how to solve this because put n times a add(x) isn't a good style ;-)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

甜嗑 2024-09-07 20:50:52

当您更改 ArrayList 的容量时,它不会创建任何元素,它只是保留可能存在元素的内存。你可以检查调整容量前后的大小,你会发现它没有变化。

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

When you change the capacity of an ArrayList it doesn't create any elements, it just reserves memory where there could be elements. You can check the size before and after adjusting the capacity and you will see that it does not change.

The purpose of changing the capacity is if you know in advance how many elements you will have, then you can avoid unnecessary repeated resizing as you add new elements, and you can avoid memory wastage from excess unused capacity.

无力看清 2024-09-07 20:50:52

如果您不喜欢直接使用自己的循环和列表 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。其他类仍然可以更改支持数组的内容,但无法增加其大小或容量。

If you don't like using your own loop and the list add method directly then there is another way. Create your ArrayList with the number of elements you want it directly like this:

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

Or, if you already have a list that you want to expand the size by n elements:

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

(Note, I assumed here that the list would be holding Integer objects, but you can change this to your custom type. If you are working with raw/pre-Java 5 types then just drop the generic declarations.)

As for your actual question: capacity != contents. An ArrayList internally has both a physical array and a count of what is actually in it. Increasing the capacity, changes the internal array so it can hold that many elements, however, the count does not change. You need to add elements to increase that count.

On the other hand, if you are just trying to set specific elements and know the maximum that you want to use, why not use an array directly? If you then need to pass this array to an API that takes Lists, then use Arrays.asList. The other classes could still change contents of your backing array but it would not be able to increase the size or capacity of it.

丢了幸福的猪 2024-09-07 20:50:52

正如其他人回答的那样,ensureCapacity() 仅与性能相关,普通用户不经常使用。

来自 Bruce Eckel 的 Thinking in Java 书中:

在私人消息中,约书亚·布洛赫 (Joshua Bloch)
写道:“......我相信我们犯了错误
允许实现细节(例如
作为哈希表大小和负载因子)
到我们的 API 中。客户应该
也许可以告诉我们最大的预期
集合的大小,我们应该
从那里拿走它。客户可以轻松
选择弊大于利
这些参数的值。作为一个
极端的例子,考虑向量
容量增量。没有人应该永远
设置这个,我们不应该
提供了它。如果您将其设置为任何
非零值,渐近成本
一系列追加来自线性
至二次方。换句话说,它
破坏你的表现。随着时间的推移,
我们开始明白这一点
之类的事情。如果你看
IdentityHashMap,你会看到它
没有低级调整参数”

As others have answered, ensureCapacity() is just related to performance, is not frequently used by the common user.

From Bruce Eckel's Thinking in Java book:

In a private message, Joshua Bloch
wrote: "... I believe that we erred by
allowing implementation details (such
as hash table size and load factor)
into our APIs. The client should
perhaps tell us the maximum expected
size of a collection, and we should
take it from there. Clients can easily
do more harm than good by choosing
values for these parameters. As an
extreme example, consider Vector's
capacityIncrement. No one should ever
set this, and we shouldn't have
provided it. If you set it to any
non-zero value, the asymptotic cost of
a sequence of appends goes from linear
to quadratic. In other words, it
destroys your performance. Over time,
we're beginning to wise up about this
sort of thing. If you look at
IdentityHashMap, you'll see that it
has no low-level tuning parameters"

纸短情长 2024-09-07 20:50:52

您收到此异常是因为 ensureCapacity() 仅确保分配了足够的内存来将对象添加到 ArrayList,我相信这是在您想一次添加多个对象而不必这样做的情况下重新定位内存。

要执行您想要的操作,您必须首先使用 null 元素启动 ArrayList...

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

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

然后您可以通过索引引用列表中的对象,并且不会收到异常。

You are getting this exception because ensureCapacity() only makes sure that there is enough memory allocated for adding objects to an ArrayList, I believe this is in case you want to add multiple objects at once, without having to relocate memory.

To do what you want you would have to initiate the ArrayList with null elements first...

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

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

Then you have objects in the List that you can reference via index and you wont receive the exception.

王权女流氓 2024-09-07 20:50:52

也许您应该重新考虑使用 List 的选择。如果要以奇数顺序添加元素,Map 可能会更合适。

这是否合适取决于我目前尚不了解的有关您的用法的知识。

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

Perhaps you should rethink the choice of using List<Double>. It might be that a Map<Integer,Double> would be more appropriate if elements are to be added in an odd order.

Whether this is appropriate depends on knowledge about your usage that I don't have at the moment though.

Is the data structure eventually going to be completely filled, or is the data sparse?

浅听莫相离 2024-09-07 20:50:52

其他人对 EnsureCapacity() 的评价...

您应该编写一个像 DynamicArrayList 扩展 ArrayList 这样的类。然后只需重写 add(n,x) 来处理指定的 for 循环 add(null) 逻辑。

what other people said about ensureCapacity() ...

you should write a class like DynamicArrayList extends ArrayList. then just overrride add(n,x) to do with for loop add(null) logic specified about.

眼眸印温柔 2024-09-07 20:50:52

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);

ensureCapacity() has another purpose. It should be used in cases when you get to know the required size of the List after it has been constructed. If you know the size before it is constructor, just pass it as a an argument to the constructor.

In the former case use ensureCapacity() to save multiple copying of the backing array on each addition. However, using that method leaves the structure in a seemingly inconsistent state

  • the size of the backing array is increased
  • the size field on the ArrayList isn't.

This, however, is normal, since the capacity != size

Use the add(..) method, which is the only one that is increasing the size field:

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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文