【问题标题】:Groovy, collating list causes concurrentmodification exceptionGroovy,整理列表导致并发修改异常
【发布时间】:2012-03-21 03:33:43
【问题描述】:

我还在学习 Groovy 的诀窍,从昨晚开始,这个问题就一直困扰着我。不知道为什么它会抛出 concurrentmod 异常......(Java 1.6,Groovy 1.8.4)

我有一个键列表... [1,2,3,4,5,6,7,8,9,10,11,12,13]

我使用从here 获得的自定义函数partitionList(keys,3) 整理列表(不能使用java.List.Collat​​e,不在1.8.6 上)

现在我有一个列表... [[0,1,2],[3,4,5],[6,7,8],[9,10,11],[12,13]]

如果创建的子列表的数量是奇数,我删除最后一个子列表[12,13] 并将其键重新分配到其他子列表中按顺序开始,创建...

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

迭代最后一个子列表的值时发生异常。不知道为什么,因为我正在迭代一个列表并在该循环中更改一个完全不同的列表......

更新:

有趣....如果我不使用 paritionList() 函数,替换 def keyRanges = partitionList( keys, 3) 带有明确的列表列表... def keyRanges = [[0,1,2],[3,4,5],[6,7,8],[9,10,11],[12,13]] 问题消失了。所以我相信 partitionList() 函数正在做一些导致异常的事情

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
    }
}

【问题讨论】:

    标签: arrays list groovy iteration concurrentmodification


    【解决方案1】:

    您使用的partitionList 方法将列表与List.getAt(Range) 分开。这会将视图返回到原始列表中,但不会复制数据,因此对子列表的任何修改也会影响原始列表。

    这意味着lastKeyRangekeyRanges 共享数据,并且添加到其中一个子列表会间接影响您正在迭代的子列表。与其修改子列表,不如创建一个新的。例如:

    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
    
        }
    }
    

    【讨论】:

    • 工作得很好,感觉它与原始列表的句柄有关...谢谢!
    • 是否可以在 partitionList() 本身中实现此增强功能?将提供更清洁、更有效的解决方案。只是想知道
    猜你喜欢
    • 2012-02-03
    • 1970-01-01
    • 1970-01-01
    • 2016-11-19
    • 2013-03-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多