为什么ArrayList输出的顺序是无序的?

11

我已经编写了一个Java程序,用于将整数添加到ArrayList中并从ArrayList中删除该整数,但它没有给我正确的结果。下面是我的代码:

public static void main(String args[])
  {
    ArrayList<Integer> a=new ArrayList<Integer>();

    a.add(6);
    a.add(7);
    a.add(8);
    a.add(9);

    for(int i=0;i<=a.size();i++)
    {

        System.out.println("Removed Elements=>"+a.remove(i));
    }
  }

它给我以下输出结果:

    Removed Elements=>6
Removed Elements=>8
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 2, Size: 2
    at java.util.ArrayList.RangeCheck(ArrayList.java:547)
    at java.util.ArrayList.remove(ArrayList.java:387)
    at CollectionTemp.main(CollectionTemp.java:19)
为什么我得到了这样的输出?

5
在我看来,输出结果是正确的。你原本期望得到的是什么? - kiheru
1
这是一个关于如何解决这个问题的好帖子。 - krishnakumarp
2
用调试器逐步执行该代码可能是一个好主意,即使下面的答案已经解释了它。在每一步之后查看 a 的内容。 - hyde
@Pshemo 代码使用索引访问,没有并发修改发生,只是从无效的整数索引中删除。 - hyde
9
在迭代集合时请勿更改其内容,这是个不好的想法。 - rossipedia
显示剩余3条评论
13个回答

49

您的数组:

a[0]=6
a[1]=7 <-- i
a[2]=8
a[3]=9

然后您移除1,i增加到2:

a[0]=6
a[1]=8
a[2]=9 <-- i

请记住,数组索引从0开始,所以最后一个元素的索引为a.length- 1

您会收到此异常是因为循环条件为i <= a.size(),因此在最后一次迭代时:

a[0] = 7
a[1] = 9
  2  <-- i

19

当你从列表或任何集合中删除项目时,你可以使用迭代器,或者像这样使用反向循环。

for (int i = (a.size() - 1); i >= 0; i--) {
    System.out.println("Removed Elements=>" + a.remove(i));
}

通过向后推进,您可以避免其他答案中记录的增量问题。


9

第一次迭代,a.remove(i)会导致元素7被移除,这个被remove方法返回。

第二次迭代时,列表的大小为3,你要移除索引2处的元素,即9。所以remove方法返回9。

简而言之

Iteration | Size of list | index being removed | element removed
----------+--------------+---------------------+----------------
    1     |      4       |          1          |       7   
    2     |      3       |          2          |       9  

另外,i<=a.size() 应该改为 i<a.size() - Maroun
另外,如果您想删除第一个元素,应将 i 设置为 0,因为 ArrayList 是基于零的。 - Ben Dale
@MarounMaroun,哇..谢谢 :) 有什么方法可以让我快速完成吗? - Prasad Kharkar

9
如果您想要一个前向循环来删除所有元素,可以使用以下代码:
while(!a.isEmpty())
{
    System.out.println("Removed Elements=>" + a.remove(0));
}

4
您的问题在于,当您删除元素时,会调整ArrayList的大小。然而,您的循环计数器没有更新,因此您会超出ArrayList的边界进行迭代。 ArrayList.remove(index)从数组中移除了元素,不仅仅是ArrayList的内容,而且实际上随着您删除项,它会重新调整ArrayList的大小。
首先,您删除了ArrayList的第一个元素。
Removed Elements=>6

这里的列表已从大小4调整为大小3。现在索引0处的元素是7。

接下来,您转向索引1处的元素。这是数字8。

Removed Elements=>8

这里 ArrayList 已经被调整大小为 2。因此只有索引为 0 和 1 的元素。

接下来,您将步进到索引为 2 的位置。

Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 2, Size: 2
    at java.util.ArrayList.RangeCheck(ArrayList.java:547)
    at java.util.ArrayList.remove(ArrayList.java:387)
    at CollectionTemp.main(CollectionTemp.java:19)

没有第二个索引,因此会出现IndexOutOfBoundsException异常。


0

我不理解你想要移除什么。如果你想要清空列表,只需要调用clear()方法即可。如果你试图移除列表中包含的对象,则应该知道ArrayList包含对象而不是原始整数。当你添加它们时,你正在执行以下操作:

a.add(Integer.valueOf(6));

在ArrayList中有两种删除方法:

remove(Object o) //Removes the first occurrence of the specified element from this list

以及你正在调用的函数:

remove(int index) //Removes the element at the specified position in this list

也许你应该先调用第一个:

 a.remove(Integer.valueOf(i));

0
ArrayList的索引从零开始,但你的循环从1开始删除。在添加元素后,你的arraylist看起来像这样:
0 - 6
1 - 7
2 - 8
3 - 9

因为你的循环从1开始计数,所以你首先要移除标记为1的元素,即7。 然后列表将变为如下形式:
0 - 6
1 - 8
2 - 9

然后循环将删除标记为2的元素,该元素现在为9。

因此,两个错误是从1开始而不是0,并在删除某些内容后递增计数器(删除元素后的所有元素将向下移动)。


0
在第一次迭代中,i从1开始,所以你的第二个元素被移除了,即7。现在列表为
6
8
9

下一次迭代是2,因此第三个元素9被移除。

0

循环中的 i 值经历以下变化:

0 1 2 3 4

数组的索引值为 0、1、2、3。

循环将运行值为 0、1、2、3、4。

数组未按顺序显示,因为当一个值被移除时,下一个值可用于索引 0。

在 i=2 时,数组大小为 2,最大索引为 1,因此遇到了 IndexOutofBound 异常。

请使用以下循环:

    while(a.size()>0)
    {
     System.out.println("Removed Elements=>"+a.remove(0));
    } 

0

索引从0开始,到size-1结束

你的循环从1到size-2


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接