2012-03-02 67 views
2

不斷學習Groovy的繩索,這個問題自昨晚以來一直困擾着我。不知道爲什麼它拋出異常concurrentmod ...(Java 1.6的,Groovy的1.8.4)Groovy,整理列表導致併發修改異常

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

我整理使用自定義函數partitionList(keys,3)我從拿到名單here(不能用java.List.Collat​​e,而不是1.8.6)

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

如果創建子列表的個數是奇數,我刪除最後一個子列表[12,13]和redistr ibute其鍵之間的其他子列表開始爲了,創造...

[[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]] 問題消失。所以我帶領相信的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 
    } 
} 

回答

2

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 

    } 
} 
+0

工作很漂亮,感覺它與原始列表的處理有關......謝謝! – raffian 2012-03-02 17:08:37

+0

是否有可能在partitionList()本身中實現此增強功能?將爲更清潔,更高效的解決方案做出貢獻。就是想 – raffian 2012-03-02 20:27:56