AFAIK, there are two approaches:
For instance,
List<Foo> fooListCopy = new ArrayList<Foo>(fooList);
for(Foo foo : fooListCopy){
// modify actual fooList
}
and
Iterator<Foo> itr = fooList.iterator();
while(itr.hasNext()){
// modify actual fooList using itr.remove()
}
Are there any reasons to prefer one approach over the other (e.g. preferring the first approach for the simple reason of readability)?
This question is related to
java
collections
iteration
I would choose the second as you don't have to do a copy of the memory and the Iterator works faster. So you save memory and time.
Old Timer Favorite (it still works):
List<String> list;
for(int i = list.size() - 1; i >= 0; --i)
{
if(list.get(i).contains("bad"))
{
list.remove(i);
}
}
Benefits:
Only second approach will work. You can modify collection during iteration using iterator.remove()
only. All other attempts will cause ConcurrentModificationException
.
In Java 8, there is another approach. Collection#removeIf
eg:
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.removeIf(i -> i > 2);
You can't do the second, because even if you use the remove()
method on Iterator, you'll get an Exception thrown.
Personally, I would prefer the first for all Collection
instances, despite the additional overheard of creating the new Collection
, I find it less prone to error during edit by other developers. On some Collection implementations, the Iterator remove()
is supported, on other it isn't. You can read more in the docs for Iterator.
The third alternative, is to create a new Collection
, iterate over the original, and add all the members of the first Collection
to the second Collection
that are not up for deletion. Depending on the size of the Collection
and the number of deletes, this could significantly save on memory, when compared to the first approach.
Are there any reasons to prefer one approach over the other
The first approach will work, but has the obvious overhead of copying the list.
The second approach will not work because many containers don't permit modification during iteration. This includes ArrayList
.
If the only modification is to remove the current element, you can make the second approach work by using itr.remove()
(that is, use the iterator's remove()
method, not the container's). This would be my preferred method for iterators that support remove()
.
why not this?
for( int i = 0; i < Foo.size(); i++ )
{
if( Foo.get(i).equals( some test ) )
{
Foo.remove(i);
}
}
And if it's a map, not a list, you can use keyset()
Source: Stackoverflow.com