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?
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).
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.
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.
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);
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)
.
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:
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With