2

まだ Groovy の使い方を学んでいますが、昨夜からこの問題に悩まされていました。なぜそれがconcurrentmod例外をスローしているのかわかりません...(Java 1.6、Groovy 1.8.4)

私は鍵のリストを持っています... [1,2,3,4,5,6,7,8,9,10,11,12,13]

ここ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()置き換え ます... 問題はなくなります。だから私は partitionList() 関数が例外を引き起こしている何かをしていると信じるようになりましたdef keyRanges = partitionList( keys, 3)def keyRanges = [[0,1,2],[3,4,5],[6,7,8],[9,10,11],[12,13]]

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

1 に答える 1

2

使用しているメソッドは、 List.getAt(Range)partitionListでリストを分割します。これにより、ビューが元のリストに返されますが、データはコピーされないため、サブリストへの変更は元のリストにも影響します。

これは、 がとlastKeyRangeデータを共有しkeyRanges、サブリストの 1 つに追加すると、反復しているサブリストに間接的に影響することを意味します。サブリストを変更するのではなく、新しいものを作成するだけです。例えば:

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

    }
}
于 2012-03-02T16:55:33.900 に答える