Use an Iterator instead and use Iterator#remove method:
for (Iterator<String> it = a.iterator(); it.hasNext(); ) {
String str = it.next();
if (!str.equals("foo") || !str.equals("bar")) {
it.remove();
}
}
From your question:
messing with for iterators is not really good practice
In fact, if you code oriented to interfaces and use List instead of ArrayList directly, using get method could become into navigating through all the collection to get the desired element (for example, if you have a List backed by a single linked list). So, the best practice here would be using iterators instead of using get.
what is the best practice to remove items from a list efficiently?
Not only for Lists, but for any Collection that supports Iterable, and assuming you don't have an index or some sort of key (like in a Map) to directly access to an element, the best way to remove an element would be using Iterator#remove.
Videos
Use an Iterator instead and use Iterator#remove method:
for (Iterator<String> it = a.iterator(); it.hasNext(); ) {
String str = it.next();
if (!str.equals("foo") || !str.equals("bar")) {
it.remove();
}
}
From your question:
messing with for iterators is not really good practice
In fact, if you code oriented to interfaces and use List instead of ArrayList directly, using get method could become into navigating through all the collection to get the desired element (for example, if you have a List backed by a single linked list). So, the best practice here would be using iterators instead of using get.
what is the best practice to remove items from a list efficiently?
Not only for Lists, but for any Collection that supports Iterable, and assuming you don't have an index or some sort of key (like in a Map) to directly access to an element, the best way to remove an element would be using Iterator#remove.
You have three main choices:
Use an
Iterator, since it has that handyremovemethod on it. :-)Iterator<String> it = list.iterator(); while (it.hasNext()) { if (/*...you want to remove `it.next()`...*/) { it.remove(); } }Loop backward through the list, so that if you remove something, it doesn't matter for the next iteration. This also has the advantage of only calling
list.size()once.for (int index = list.size() - 1; index >= 0; --index) { // ...check and optionally remove here... }Use a
whileloop instead, and only increment the index variable if you don't remove the item.int index = 0; while (index < list.size()) { if (/*...you want to remove the item...*/) { list.removeAt(index); } else { // Not removing, move to the next ++index; } }
Remember that unless you know you're dealing with an ArrayList, the cost of List#get(int) may be high (it may be a traversal). But if you know you're dealing with ArrayList (or similar), then...
for (Iterator<String> iter = list.listIterator(); iter.hasNext(); ) {
String a = iter.next();
if (...) {
iter.remove();
}
}
Making an additional assumption that the list is of strings.
As already answered, an list.iterator() is needed. The listIterator can do a bit of navigation too.
–---------
Update
As @AyushiJain commented, there is
list.removeIf(...);
You need to use Iterator and call remove() on iterator instead of using for loop.