sanlalala
sanlalala

Reputation: 17

Change MutableList during Iteration

Ok, so. I'm absolutely stumped by this problem. I have a function, which sorts a list of objects and gives it back, à la 1, 1.1, 1.2, 1.2.1, 2, 2.2, 3.

fun getFolderHierachy(allFolders: List<FolderEntity>): List<FolderEntity>? {

  //puts the entrypoints( 1, 2, 3) in a list
        if (allFolders.isNotEmpty()) {
            val foldersSorted: MutableList<FolderEntity> = mutableListOf()
            allFolders.forEach {
                if (it.parentDir == null) {
                    foldersSorted.add(it)
                }
            }

// should insert an element, after the matching one ( 1, 1.1, 2, 3) 
            while (foldersSorted.size != allFolders.size) {
                foldersSorted.forEach { parentFolder ->
                    allFolders.forEach {
                        if (!foldersSorted.contains(it)) {
                            if (it.parentDir == parentFolder.uid) {
                                val index = foldersSorted.indexOf(parentFolder)
                                foldersSorted.add(index + 1, it)
                            }
                        }
                    }
                }
            }
            println(foldersSorted)
            return foldersSorted
        }
        return null
    }

I know should work, because it already delievered me the correct results. However after the last update from my master, it throws this error:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: de.ur.mi.audidroid, PID: 16634
    java.util.ConcurrentModificationException
        at java.util.ArrayList$Itr.next(ArrayList.java:860)
        at de.ur.mi.audidroid.viewmodels.FolderViewModel.getFolderHierachy(FolderViewModel.kt:206)
        at de.ur.mi.audidroid.viewmodels.FolderViewModel$initFolderSorting$1.onChanged(FolderViewModel.kt:45)
        at de.ur.mi.audidroid.viewmodels.FolderViewModel$initFolderSorting$1.onChanged(FolderViewModel.kt:20)
        at androidx.lifecycle.MediatorLiveData$Source.onChanged(MediatorLiveData.java:152)
        at androidx.lifecycle.LiveData.considerNotify(LiveData.java:131)
        at androidx.lifecycle.LiveData.dispatchingValue(LiveData.java:149)
        at androidx.lifecycle.LiveData.setValue(LiveData.java:307)
        at androidx.lifecycle.LiveData$1.run(LiveData.java:91)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

The update didn't even change anything relevant to this function. I know it hast something to do with the change of the list while iterating, but shouldn't MutableList take care of that? I'm so confused at how I should change it to make it work again, please help.

Upvotes: 0

Views: 1297

Answers (1)

Mohamed Alsaid
Mohamed Alsaid

Reputation: 960

When using foreach you use the List's iterator which doesn't allow concurrent modification until the loop exists. To get around this, use a standard for loop.

while (foldersSorted.size != allFolders.size) {
    for (i in 0 until foldersSorted.size) {
        val parentFolder = foldersSorted[i]
        // Rest of code
    }
}

Upvotes: 1

Related Questions