Java 8+
The Collection
interface now provides a removeIf
method that modifies it in place, to which you provide a predicate that returns true
if the element should be removed.
You can thus use a lambda like so:
name.removeIf(name -> name.equals("Meg"));
A method reference can be used as well to be more concise. The following code will also work if there are null
elements.
name.removeIf("Meg"::equals);
If you do not want to modify the old list, you can use Stream
and filter
to get a List
of all the items that should be retained by negating the condition.
final List<String> filtered = name.stream()
.filter(name -> !"Meg".equals(name))
.collect(Collectors.toList());
If you specifically need an ArrayList
, use Collectors.toCollection
with a constructor reference instead.
final ArrayList<String> filtered = name.stream()
.filter(name -> !"Meg".equals(name))
.collect(Collectors.toCollection(ArrayList::new));
Pre Java 8
The issue is that the ArrayList is being modified while being iterated over, which changes its size and shifts later elements forward; this is a problem if there are consecutive elements that need to be removed. You need to decrease the index by one each time you remove an element since that index will now refer to the next element.
for (int i = 0; i < name.size(); i++) {
String oldName = name.get(i);
if (oldName.equals("Meg")) {
name.remove(i);
i--;//Important!
}
}
Looping backwards will also fix this problem, as elements will never be shifted to a position that have yet to be checked.
for (int i = name.size() - 1; i >= 0; i--) {
String oldName = name.get(i);
if (oldName.equals("Meg")) {
name.remove(i);
}
}
Generally, using an Iterator
is the most appropriate for this sort of operation, as it supports removing elements while iterating through calling Iterator#remove
. This also modifies the List
in place. For more complex operations, consider using a ListIterator
.
final Iterator<String> it = name.iterator();
while(it.hasNext()){
final String name = it.next();
if(name.equals("Meg")){
it.remove();
}
}