Is it safe to remove multiple items from an ArrayList while iterating through it with an iterator?
Iterator<String> iterator = nameList.iterator();
while(iterator.hasNext()){
String s = iterator.next();
List<String> list = work(s);
for (String s1 : list) {
nameList.remove(s1);
}
}
The work()
method gives back a list of names that should be removed from the nameList, during the runtime of while loop.
No, it's not safe, and can throw ConcurrentModificationException
. You can collect all the elements to be removed in a temporary List
, and then call list.removeAll(tmpList)
after the while loop to perform the removal.
Iterator<String> iterator = nameList.iterator();
List<String> removed = new ArrayList<>();
while(iterator.hasNext()){
String s = iterator.next();
removed.addAll(work(s));
}
list.removeAll(removed);
I realize this can be less efficient, since you might be calling work(s)
on String
s the should have been removed from the List
earlier. This can be improved by changing tempList
to a Set
, and only calling work(s)
for String
s not in the Set
:
Iterator<String> iterator = nameList.iterator();
Set<String> removed = new HashSet<>();
while(iterator.hasNext()){
String s = iterator.next();
if (!removed.contains(s)) {
removed.addAll(work(s));
}
}
list.removeAll(removed);
You can implement your logic if you use a ListIterator which is fail-safe. Below is a basic example :
Set<String> removed = new HashSet<>();
ArrayList<String> nameList = new ArrayList<String>();
ListIterator<String> iterator = nameList.listIterator();
while(iterator.hasNext()){
String s = iterator.next();
if (!removed.contains(s)) {
removed.addAll(work(s));
}
}
nameList.removeAll(removed);
System.out.println(nameList);
With your logic, you have to account the performance. If performance is not a factor, you can go ahead and add/remove from a list through ListIterator.
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