Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ArrayList.remove gives different result when called as Collection.remove

Tags:

This code:

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

    } 

prints: abc

Meanwhile this one:

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

    } 

prints: ab

However it should print the same result... What's the problem?

like image 719
Hicham Moustaid Avatar asked Feb 28 '16 09:02

Hicham Moustaid


People also ask

What happens when you remove something from an ArrayList?

If you call ArrayList. remove() the element at the given index is removed from the list (and all elements following it move down one index).

Does removing ArrayList return anything?

ArrayList. remove() removes the first occurrence of the specified element from this ArrayList, if it is present. If the object/element is not present, then remove(obj) does nothing. If the specified object is present and removed, then remove() returns true, else it returns false.

How does the remove method work in ArrayList?

The remove() method is used to remove an element at a specified index from ArrayList. Shifts any subsequent elements to the left (subtracts one from their indices). The index of the element to be removed.

Which ArrayList method removes all the items from an ArrayList collection?

The Java ArrayList removeAll() method removes all the elements from the arraylist that are also present in the specified collection. The syntax of the removeAll() method is: arraylist. removeAll(Collection c);


2 Answers

Collection has only boolean remove(Object o) method, which removes the passed object if found.

ArrayList also has public E remove(int index), which can remove an element by its index.

Your first snippet calls boolean remove(Object o), which doesn't remove anything, since your ArrayList doesn't contain 1. Your second snippet calls public E remove(int index) and removes the element whose index was 1 (i.e. it removes "b").

The different behavior results from the fact that method overload resolution occurs at compile time and depends on the compile time type of the variable for which you are calling the method. When the type of col is Collection, only remove methods of the Collection interface (and methods inherited by that interface) are considered for overloading resolution.

If you replace col.remove(1) with col.remove("b"), both snippets would behave the same.

As Tamoghna Chowdhury commented, boolean remove(Object o) can accept a primitive argument - int in your case - due to auto-boxing of the int to an Integer instance. For the second snippet, the reason public E remove(int index) is chosen over boolean remove(Object o) is that the method overloading resolution process first attempts to find a matching method without doing auto-boxing/unboxing conversions, so it only considers public E remove(int index).

like image 124
Eran Avatar answered Oct 29 '22 22:10

Eran


To safely remove from a Collection while iterating over it, you should use an 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);
}

Regarding, the reason why removal from collection is not working for you while the ArrayList worked is because of the following:

  1. The java.util.ArrayList.remove(int index) method removes the element at the specified position in this list. Shifts any subsequent elements to the left (subtracts one from their indices). Hence, this one worked for you.

  2. The java.util.Collection.remove(Object o) method removes a single instance of the specified element from this collection, if it is present (it is an optional operation). More formally, removes an element e such that (o==null ? e==null : o.equals(e)), if this collection contains one or more such elements. Returns true if this collection contained the specified element (or equivalently, if this collection changed as a result of the call).

Hope, this helps.

like image 25
The Roy Avatar answered Oct 29 '22 22:10

The Roy