【问题标题】:Removing Elements From Array List从数组列表中删除元素
【发布时间】:2015-09-14 22:24:00
【问题描述】:

谁能解释remove()ArrayList 是如何工作的?

public class ListTest { 
    public static void main(String[] args) {
        List list = new ArrayList();
        for(int i=0;i<10;i++)
        {
            list.add(i);
        }
        System.out.println("Size of list before removing :"+list.size());

        for(int i=0;i<list.size();i++)
        {
            list.remove(i);         
        }
        System.out.println("Size of list after removing all elements :"+list.size());
    }
}

输出

删除前的列表大小:10
删除所有元素后的列表大小:5

我做错了什么?

【问题讨论】:

  • Remove 将删除所有索引的所有值,但 arraylist 大小将保持不变。如果您使用list.remove() with list.trimToSize()`,那么list.size() 也将为零。
  • @Clairvoyant "Remove 将删除所有索引的所有值,但 arraylist 大小将保持不变。" 内部数组的大小,但不是 @987654327 的返回值@。 OP 的问题是他没有删除所有元素。
  • 想到clear()
  • @Anuj FYA- 观察到您提出了 3 个问题但不接受答案。如果提供的答案都没有回答您的问题或对您有帮助,并且您有自己的答案,请发布它,以便其他人可以从中受益。

标签: java arraylist collections core


【解决方案1】:

list.remove(i); 移动被移除元素之后的所有元素的索引。因此,在调用list.remove(0) 之后,位置 1 的前一个元素将移动到位置 0,并且您的循环将永远不会删除它,因为 i 递增。如您所见,您的循环只会删除一半的元素。

此循环将删除所有元素:

while(list.size()>0)
{
    list.remove(0);
}

【讨论】:

  • 小心ConcurrentModificationException,应该使用迭代器。
  • @MarounMaroun 我的代码中没有出现 ConcurrentModificationException 的原因(除非其他线程同时访问 ArrayList,如果我使用迭代器,这也可能是一个问题)。
【解决方案2】:

要在迭代集合时安全地从集合中删除,您应该使用迭代器。例如: 列表名称 = ....

Iterator<Integer> i = names.iterator();

while (i.hasNext()) {  
Integer s = i.next(); 
// must be called before you can call  i.remove()      // Do something     i.remove(); }

根据文档删除数组列表的位置

该集合包含一个或多个此类元素。 集合,如果它存在(可选操作)。更正式地说,如果集合包含一个或多个这样的元素,则删除一个元素,例如 (o==null ? e==null : o.equals(e))。

这意味着如果在依赖 equals() 的情况下使用它并删除匹配发生的第一个实例。

【讨论】:

    【解决方案3】:

    删除此列表中指定位置的元素。移动任何 左边的后续元素(从它们的索引中减去一个)。

    如上所述,从ArrayList#remove 文档中可以看出,删除元素后 ArrayList 将自行调整大小,因此您的 ArrayList 实际上每次都在缩小,因此您的 FOR 循环只运行了一半。

           for(int i=0;i<list.size();i++)
            {
                System.out.println(i);
                list.remove(i);
    
            }
    

    输出:

    0
    1
    2
    3
    4
    

    如果您检查remove 是为了了解目的,那么您可以考虑使用ArrayList#clear,这将令人信服地一次性清空您的ArrayList

    另外,检查ArrayList#remove 的重载方法,它允许您使用索引以及实际本身来删除元素,但在每个删除情况下,ArrayList 都会调整大小。

    希望这会有所帮助!

    【讨论】:

      【解决方案4】:

      因为ArrayListdynamically resizing array 数据结构,这意味着它被实现为具有初始(默认)固定大小的数组。当它被填满时,数组将被扩展为一个双倍大小的数组。此操作成本高,因此您希望尽可能少。

      int newCapacity = (oldCapacity * 3)/2 + 1;
      

      当您从ArrayList 中删除元素时 - 他不会缩小尺寸。
      这是您需要知道的一件事。

      如果你想在删除项目后刷新内存使用

      public void trimToSize()
      

      此方法将此ArrayList 实例的容量修剪为列表的当前大小。应用程序可以使用此操作来最小化ArrayList 实例的存储。

      【讨论】:

      • “当你从 ArrayList 中删除元素时 - 他没有缩小大小。”没有得到这部分..
      【解决方案5】:

      因为 ArrayList 本质上是动态的。它的 remove 函数必须维护此属性,并且每次调用它时都会动态减小 ArrayList 的大小。 Remove 只是将 List 中的元素移动一个索引,以便每次删除该元素并减小列表的大小。

      列表大小不是静态,每次从列表中删除元素时,它都会不断减小。在您的情况下,最初列表的大小是 10。当您从列表中删除第一个元素时,大小会减少到 9。当循环中的 i = 4 时,列表的大小将为 5。现在进一步增加 i 将违反循环的条件

      i< list.size()
      

      因此,当您的列表大小仍为 5 时,循环将在那里终止。

      只需在删除的 for 循环中添加下面提到的单行,以便更好地理解。

      System.out.println("list size is :"+list.size() +" and i is "+i);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-03-30
        • 2015-06-12
        • 2013-12-27
        • 1970-01-01
        • 1970-01-01
        • 2017-03-05
        相关资源
        最近更新 更多