当调用Collection.remove时,ArrayList.remove会给出不同的结果

Hic*_*aid 20 java iteration collections

这段代码:

    Collection<String> col = new ArrayList<String>();    
    col.add("a");
    col.add("b");
    col.add("c");
    for(String s: col){       
       if(s.equals("b"))
             col.remove(1);  
       System.out.print(s);  

    } 
Run Code Online (Sandbox Code Playgroud)

打印: abc

同时这一个:

    ArrayList<String> col = new ArrayList<String>();    
    col.add("a");
    col.add("b");
    col.add("c");
    for(String s: col){       
       if(s.equals("b"))
             col.remove(1);  
       System.out.print(s);  

    } 
Run Code Online (Sandbox Code Playgroud)

打印: ab

但它应该打印相同的结果......有什么问题?

Era*_*ran 30

Collection只有boolean remove(Object o)方法,如果找到则删除传递的对象.

ArrayList还有public E remove(int index),可以通过索引删除元素.

您的第一个代码段调用boolean remove(Object o),不会删除任何内容,因为您ArrayList不包含1.您的第二个片段调用public E remove(int index)并删除索引为1的元素(即删除"b").

不同的行为是由于方法重载解析在编译时发生并且取决于您为其调用方法的变量的编译时类型而导致的.当类型为colis时Collection,只考虑接口的方法(以及removeCollection接口继承的方法)来重载分辨率.

如果替换col.remove(1)col.remove("b"),则两个片段的行为都相同.

正如Tamoghna Chowdhury评论的那样,boolean remove(Object o)可以接受一个原始论证 - int在你的情况下 - 由于自动装箱int到一个Integer实例.对于第二个片段,public E remove(int index)选择的原因是boolean remove(Object o)方法重载解析过程首先尝试查找匹配方法而不进行自动装箱/取消装箱转换,因此它只考虑public E remove(int index).

  • 还应该补充说,在迭代它时修改一个集合通常是个坏主意*.有些语言甚至不允许这样做.这就是你没有看到打印出"c"的原因.它仍然在那里(只删除了"b"),但由于删除,你已经提前一步到达了你的收藏的"结尾". (4认同)

The*_*Roy 9

为了安全地删除Collection迭代它,你应该使用Iterator.

ArrayList<String> col = new ArrayList<String>();    
col.add("a");
col.add("b");
col.add("c");

Iterator<String> i = col.iterator();
while (i.hasNext()) {
   String s = i.next(); // must be called before you can call remove
   if(s.equals("b"))
      i.remove();
   System.out.print(s);
}
Run Code Online (Sandbox Code Playgroud)

关于,由于以下原因,删除收集对您不起作用的原因ArrayList是:

  1. java.util.ArrayList.remove(int index)方法删除此列表中指定位置的元素.将任何后续元素向左移位(从索引中减去一个).因此,这个适合你.

  2. java.util.Collection.remove(Object o)方法从该集合中删除指定元素的单个实例(如果存在)(它是可选操作).更正式地,去除的元件e,使得(o==null ? e==null : o.equals(e)),如果该集合包含一个或多个这样的元件.返回true此集合是否包含指定元素(或等效地,如果此集合因调用而更改).

希望这可以帮助.