Reputation: 51
I have person objects that have a gender field objects the person adds to the list then I want to remove from the list people who have man
enum class Gender{
woman, man
}
fun main(args: Array<String>) {
data class Person(var name: String, var surname: String, var gender: Gender)
val person1 = Person("Jan", "Kowalski", Gender.man)
val person2 = Person("Paweł", "Pawelski", Gender.man)
val person3 = Person("Ewa", "Miła", Gender.woman)
val person4 = Person("Gosia", "Zemvba", Gender.woman)
var PersonList = listOf<Person>(person1, person2, person3, person4).toMutableList()
val listIterator2 = PersonList.iterator()
while (listIterator2.hasNext()) {
var tmp = listIterator2.next()
if (tmp.gender == Gender.man) {
println( "deleted " + tmp)
PersonList.remove(tmp)
}
}
}
in line var tmp = listIterator2.next() i have a error
Exception in thread "main" java.util.ConcurrentModificationException
at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1012)
at java.base/java.util.ArrayList$Itr.next(ArrayList.java:966)
at TmpKt.main(tmp.kt:19)
Upvotes: 1
Views: 2320
Reputation: 2332
Iterators are not always helpful when another thread modifies the collection. I had tried many ways but then realized traversing the collection manually is much safer (backward for remove):
for (i in listPersons.size-1 downTo 0) {
myList.getOrNull(i)?.apply {
if (gender == Gender.man)
listPersons.remove(this)
}
}
Upvotes: 0
Reputation: 4340
Rather than manipulating the original list, you can produce a new list like:
val personList = listOf<Person>(person1, person2, person3, person4)
val personListUpdated = personList.filter { it.gender != Gender.man }
(or, as suggested by Tenfour04 above, removeAll
or filterNot
can also be used to invert the condition)
See this playground to try it yourself: https://pl.kotl.in/LGkr_cobj
Upvotes: 1
Reputation: 93629
You have to call remove
on the iterator itself, not the list.
val listIterator2 = PersonList.iterator()
while (listIterator2.hasNext()) {
var tmp = listIterator2.next()
if (tmp.gender == Gender.man) {
println( "deleted " + tmp)
listIterator2.remove()
}
}
It is easier to use removeAll()
than to work with the iterator directly:
personList.removeAll { it.gender == Gender.man }
Upvotes: 2