Remove elements from a list while iterating in Kotlin
This article explores different ways to remove elements from a mutable list in Kotlin that satisfies the given predicate while iterating over it using a loop or an iterator.
It is not recommended adding or removing elements from a list within a loop as an index of its elements, and its length is changed. This is because it might lead to incorrect results due to skipped elements or java.util.IndexOutOfBoundsException or java.util.ConcurrentModificationException will be thrown to avoid non-deterministic behavior at a 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
The suggested solution is to iterate backward in the list. This way, no elements will be skipped from the list.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import java.util.function.Predicate fun <T> filter(list: MutableList<T>, predicate: Predicate<T>) { for (i in list.indices.reversed()) { if (predicate.test(list[i])) { list.removeAt(i) } } } fun main() { val nums: MutableList<Int> = (1..10).toMutableList() filter(nums, Predicate { i: Int -> i % 2 == 1 }) println(nums) // [2, 4, 6, 8, 10] } |
2. Decremeting index
Another trick is to iterate forward in the list and decrement the loop index whenever an element is removed.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
import java.util.function.Predicate fun <T> filter(list: MutableList<T>, predicate: Predicate<T>) { var i = 0 while (i < list.size) { if (predicate.test(list[i])) { list.removeAt(i--) } i++ } } fun main() { val nums: MutableList<Int> = (1..10).toMutableList() filter(nums, Predicate { i: Int -> i % 2 == 1 }) println(nums) // [2, 4, 6, 8, 10] } |
3. Using Iterator’s remove() function
To avoid java.util.ConcurrentModificationException being thrown, you can use iterator’s own remove() function.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
import java.util.function.Predicate fun <T> filter(list: MutableList<T>, predicate: Predicate<T>) { val itr = list.iterator() while (itr.hasNext()) { val t = itr.next() if (predicate.test(t)) { itr.remove() } } } fun main() { val nums: MutableList<Int> = (1..10).toMutableList() filter(nums, Predicate { i: Int -> i % 2 == 1 }) println(nums) // [2, 4, 6, 8, 10] } |
4. Using removeAll() function
Alternatively, you can create a separate collection of elements to be deleted and delete them later from the list using the removeAll() function.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import java.util.function.Predicate fun <T> filter(list: MutableList<T>, predicate: Predicate<T>) { val toRemove = HashSet<T>() for (item in list) { if (predicate.test(item)) { toRemove.add(item) } } list.removeAll(toRemove) } fun main() { val nums: MutableList<Int> = (1..10).toMutableList() filter(nums, Predicate { i: Int -> i % 2 == 1 }) println(nums) // [2, 4, 6, 8, 10] } |
That’s all about removing elements from a list while iterating in Kotlin.
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 :)