Groovy,整理列表导致并发修改异常

2023-12-29

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

我有一份钥匙清单...[1,2,3,4,5,6,7,8,9,10,11,12,13]

我使用自定义函数整理列表partitionList(keys,3)我从here https://stackoverflow.com/questions/2924395/groovy-built-in-to-split-an-array-into-equal-sized-subarrays/2926548#2926548(不能使用 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]]

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

UPDATE:

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

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

The partitionList您使用的方法将列表拆分为List.getAt(范围) http://groovy.codehaus.org/groovy-jdk/java/util/List.html#getAt%28groovy.lang.Range%29。这将返回原始列表的视图,但不会复制数据,因此对子列表的任何修改也会影响原始列表。

这意味着lastKeyRange与共享数据keyRanges,并且添加到子列表之一会间接影响您正在迭代的子列表。无需修改子列表,只需创建一个新子列表即可。例如:

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

    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Groovy,整理列表导致并发修改异常 的相关文章

随机推荐