Groovy, collating list causes concurrentmodification exception

て烟熏妆下的殇ゞ 提交于 2019-12-12 20:14:42

问题


Still learning the ropes with Groovy, this problem has tripped me up since last night. Not sure why it's throwing concurrentmod exception...(Java 1.6, Groovy 1.8.4)

I have a list of keys... [1,2,3,4,5,6,7,8,9,10,11,12,13]

I collate the list using a custom function partitionList(keys,3) I got from here (can't use java.List.Collate, not on 1.8.6)

Now I've got a list of lists... [[0,1,2],[3,4,5],[6,7,8],[9,10,11],[12,13]]

If the number of sub-lists created is odd, I remove the last sub list [12,13] and redistribute its keys amongst the other sub lists starting in order, creating...

[[0,1,2,12],[3,4,5,13],[6,7,8],[9,10,11]]

The exception occurs when iterating the values of the last sub list. Not sure why since I'm iterating a list and changing an entirely different list in that loop...

UPDATE:

Interesting....if I don't use the paritionList() function, replacing def keyRanges = partitionList( keys, 3) with an explicit list of lists... def keyRanges = [[0,1,2],[3,4,5],[6,7,8],[9,10,11],[12,13]] the problem disappears. So I'm lead to believe the partitionList() function is doing something that's causing the exception

class CollateListTest {

    static main(args) {    
        def keys = (0..13).toList()

        //partition the keys into a list of lists 
        def keyRanges = partitionList( keys, 3)
        println 'Key range sets...'
        for( keyRange in keyRanges)
            println keyRange

        //if odd number of partitions, 
        //remove last sub list and redistribute values over other lists
        if( (keyRanges.size() % 2) != 0){
            def lastKeyRange = keyRanges.remove( keyRanges.size() - 1 )
            println 'removed range: ' + lastKeyRange

                    // ** EXCEPTION HERE **         
            lastKeyRange.eachWithIndex{ k, index ->
                println 'adding: ' + k
                keyRanges[ index % keyRanges.size()].add( k)
            }
        }
    }

    //from stackoverflow.com/questions/2924395/
    static def partitionList(list, size) {
        def partitions = []
        int partitionCount = list.size() / size

        partitionCount.times { partitionNumber ->
            def start = partitionNumber * size
            def end = start + size - 1
            partitions << list[start..end]
        }

        if (list.size() % size) partitions << list[partitionCount * size..-1]
        return partitions
    }
}

回答1:


The partitionList method you're using splits up the list with List.getAt(Range). This returns a view into the original list, but doesn't copy the data, so any modifications to the sublist also affect the original.

This means that lastKeyRange shares data with keyRanges, and that adding to one of the sublists indirectly affects the sublist you are iterating over. Rather than modifying the sublist, just create a new one. For example:

if( (keyRanges.size() % 2) != 0){
    def lastKeyRange = keyRanges.remove( keyRanges.size() - 1 )
    println 'removed range: ' + lastKeyRange

    lastKeyRange.eachWithIndex{ k, index ->
        println 'adding: ' + k
        def newRange = []
        newRange.addAll(keyRanges[ index % keyRanges.size()])
        newRange.add(k)
        keyRanges[ index % keyRanges.size()] = newRange

    }
}


来源:https://stackoverflow.com/questions/9536552/groovy-collating-list-causes-concurrentmodification-exception

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!