Remove elements from a list while iterating over it in Java
This post will discuss how to remove elements from a mutable list in Java that satisfies the given condition within a loop or iterator.
It is not recommended adding or removing elements from a list within a loop as an index of its elements, and the length of the list is changed. This might lead to the incorrect output, or java.util.IndexOutOfBoundsException or java.util.ConcurrentModificationException will be thrown to avoid non-deterministic behavior at later stage.
Issues with removing elements from a list in Java/Kotlin within a loop
There are several workarounds to deal with this problem. These are discussed below:
1. Iterating backwards
We have seen that moving forward in the list using a for-loop and removing elements from it might cause us to skip a few elements. One workaround is to iterate backward in the list, which does not skip anything.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.function.Predicate; class Main { // Generic method to remove elements from a list in Java public static <T> void filterList(List<T> list, Predicate<T> condition) { for (int i = list.size() - 1; i >= 0 ; i--) { if (condition.test(list.get(i))) { list.remove(i); } } } public static void main(String[] args) { List<String> colors = new ArrayList<>(Arrays.asList("BLUE", "RED", "RED", "YELLOW")); filterList(colors, i -> i.equals("RED")); System.out.println(colors); // [BLUE, YELLOW] } } |
2. Decrementing index
The idea is to iterate forward in the list and decrement the loop index whenever an element is removed. Now no elements would be skipped.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.function.Predicate; class Main { // Generic method to remove elements from a list in Java public static <T> void filterList(List<T> list, Predicate<T> condition) { for (int i = 0; i < list.size(); i++) { if (condition.test(list.get(i))) { list.remove(i); i--; } } } public static void main(String[] args) { List<String> colors = new ArrayList<>(Arrays.asList("BLUE", "RED", "RED", "YELLOW")); filterList(colors, i -> i.equals("RED")); System.out.println(colors); // [BLUE, YELLOW] } } |
3. Using Iterator.remove() method
We have seen that a ConcurrentModificationException will be thrown if we try to modify a list while iterating over it. The solution is to use the iterator’s own remove method, which removes the last element returned by the iterator.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.function.Predicate; class Main { // Generic method to remove elements from a list in Java public static <T> void filterList(List<T> list, Predicate<T> condition) { Iterator<T> itr = list.iterator(); while (itr.hasNext()) { T t = itr.next(); if (condition.test(t)) { itr.remove(); } } } public static void main(String[] args) { List<String> colors = new ArrayList<>(Arrays.asList("BLUE", "RED", "RED", "YELLOW")); filterList(colors, i -> i.equals("RED")); System.out.println(colors); // [BLUE, YELLOW] } } |
4. Use Another Collection
Instead of removing elements as moving forward in the list, we create a collection of such elements and delete them later. Depending upon the deletion condition used, this approach might fail if the list contains duplicate elements.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
import java.util.*; import java.util.function.Predicate; class Main { // Generic method to remove elements from a list in Java public static <T> void filterList(List<T> list, Predicate<T> condition) { Set<T> toRemove = new HashSet<>(); for (T item: list) { if (condition.test(item)) { toRemove.add(item); } } list.removeAll(toRemove); } public static void main(String[] args) { List<String> colors = new ArrayList<>(Arrays.asList("BLUE", "RED", "RED", "YELLOW")); filterList(colors, i -> i.equals("RED")); System.out.println(colors); // [BLUE, YELLOW] } } |
Here’s an equivalent version using the Stream API.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import java.util.*; import java.util.function.Predicate; import java.util.stream.Collectors; class Main { // Generic method to remove elements from a list in Java public static <T> void filterList(List<T> list, Predicate<T> condition) { Set<T> toRemove = list.stream().filter(condition::test).collect(Collectors.toSet()); list.removeAll(toRemove); } public static void main(String[] args) { List<String> colors = new ArrayList<>(Arrays.asList("BLUE", "RED", "RED", "YELLOW")); filterList(colors, i -> i.equals("RED")); System.out.println(colors); // [BLUE, YELLOW] } } |
That’s all about removing elements from a list while iterating over it in Java.
Suggested Read:
Remove elements from a List that satisfies a given predicate in Java
Thanks for reading.
To share your code in the comments, please use our online compiler that supports C, C++, Java, Python, JavaScript, C#, PHP, and many more popular programming languages.
Like us? Refer us to your friends and support our growth. Happy coding :)