This question already has an answer here:
In Java, is it legal to call remove on a collection when iterating through the collection using a foreach loop? For instance:
List<String> names = ....
for (String name : names) {
// Do something
names.remove(name).
}
As an addendum, is it legal to remove items that have not been iterated over yet? For instance,
//Assume that the names list as duplicate entries
List<String> names = ....
for (String name : names) {
// Do something
while (names.remove(name));
}
Use
.remove() of Interator or
Use
CopyOnWriteArrayList
It's better to use an Iterator when you want to remove element from a list
because the source code of remove is
so ,if you remove an element from the list, the list will be restructure ,the other element's index will be changed, this can result something that you want to happened.
Yes you can use the for-each loop, To do that you have to maintain a separate list to hold removing items and then remove that list from names list using
removeAll()
method,You don't want to do that. It can cause undefined behavior depending on the collection. You want to use an Iterator directly. Although the for each construct is syntactic sugar and is really using an iterator, it hides it from your code so you can't access it to call
Iterator.remove
.Instead write your code:
Note that the code calls
Iterator.remove
, notList.remove
.Addendum:
Even if you are removing an element that has not been iterated over yet, you still don't want to modify the collection and then use the
Iterator
. It might modify the collection in a way that is surprising and affects future operations on theIterator
.The java design of the "enhanced for loop" was to not expose the iterator to code, but the only way to safely remove an item is to access the iterator. So in this case you have to do it old school:
If in the real code the enhanced for loop is really worth it, then you could add the items to a temporary collection and call removeAll on the list after the loop.
EDIT (re addendum): No, changing the list in any way outside the iterator.remove() method while iterating will cause problems. The only way around this is to use a CopyOnWriteArrayList, but that is really intended for concurrency issues.
The cheapest (in terms of lines of code) way to remove duplicates is to dump the list into a LinkedHashSet (and then back into a List if you need). This preserves insertion order while removing duplicates.