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 Strings 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 Strings 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