2012-09-01 49 views
0

在處理HashSet時,我得到了concurrentModificatoin異常,因此轉移到了ConcurrentSkipListSet。雖然併發問題已解決,但我現在有一個新問題。看起來ConcurrentSkipListSet默認是靜態的。是這樣嗎?我在一個遞歸函數中使用它,它有一個迭代器遍歷它。當迭代下一個元素時,由於同一個函數的另一個重複實例所做的更改會反映到同一個對象中(通常情況下,在正常遞歸中不會出現這種情況,其中每個實例都在堆棧中分配了自己的空間)。我不希望更改反映出來。有沒有解決這個問題的方法?ConcurrentSkipListSet是靜態的嗎?

感謝提前:)

我使用Java和這裏的代碼...

public class TSA { 

    int[][] l = { { 0, 1, 30, 65535 }, { 50, 0, 15, 5 }, { 65535, 65535, 0, 15 }, { 15, 65535, 5, 0 } }; 
    int[][] g; 


    TSA() { 
     int n = 4; 
     this.g = this.l; 
     int k = 0; 
     ConcurrentSkipListSet a = new ConcurrentSkipListSet(); 

     for (int i = 0; i < n; i++) { 
      for (int j = 0; j < n; j++) { 
       this.g[i][j] = this.l[i][j]; 
      } 
     } 

     System.out.println(this.g[2][1]); 
     a.add(2); 
     a.add(3); 
     a.add(4); 

     Iterator ir = a.iterator(); 
     int[] path = new int[n]; 
     k = 0; 

     while (ir.hasNext()) { 
      ConcurrentSkipListSet b = new ConcurrentSkipListSet(); 
      b = a; 
      b.add(2); 
      b.add(3); 
      b.add(4); 

      int next = (Integer) ir.next(); 
      System.out.println("next in main is " + next); 
      System.out.println("called with " + b); 

      path[k++] = this.l[0][next - 1] + gfun(next, b); 
      System.out.println("min path is..." + path[k - 1]); 

     } 
    } 


    public static void main(final String[] args) { 
     new TSA(); 
    } 


    int gfun(final int next, final ConcurrentSkipListSet d) { 
     ConcurrentSkipListSet b = d; 

     if (b.size() != 1 && b.size() != 2) { 
      b.remove(next); 
      System.out.println(b); 

      int[] path = new int[b.size()]; 
      int k = 0; 

      Iterator ir = b.iterator(); 

      while (ir.hasNext()) { 
       int a = (Integer) ir.next(); 
       System.out.println(a + "  iterator prob " + b); 
       path[k] = this.l[next - 1][a - 1] + gfun(a, b); 
       System.out.println("path[" + k + "] is" + path[k]); 
       k = k + 1; 

      } 

      return min(path); 
     } 
     else if (b.size() == 2) { 
      System.out.println("second instance..." + next + ".." + b); 
      Iterator irrr = b.iterator(); 
      int a = (Integer) irrr.next(); 
      b.remove(next); 
      return (gfun(next, b)); 
     } 
     else { 
      Iterator irr = b.iterator(); 

      int j = (Integer) irr.next(); 
      System.out.println("inside prog size is 1" + b); 
      System.out.println("l[" + next + "][" + j + "] is " + this.l[next - 1][j - 1]); 
      int ans = this.l[next - 1][j - 1] + this.g[j - 1][0]; 
      System.out.println("l[" + next + "][" + j + "]+g[" + j + "][1] which is " + ans + " is         r    returned"); 

      return (ans); 
     } 

    } 


    private int min(final int[] path) { 
     int m = path[0]; 

     for (int i = 0; i < path.length; i++) { 
      if (path[i] < m) { 
       m = path[i]; 
      } 
     } 
     return m; 
    } 
} 

我除去集合B的元素,當函數返回到以前的狀態(while循環內的迭代器)原始集合b會受到影響。我不希望發生這種情況。有人請幫忙! :(

+0

如果你要顯示你的代碼,它將會非常有用。您對「正常遞歸」的描述雖然對我來說聽起來並不完全正確...... –

+1

也許對您知道您使用的是什麼語言也有幫助... – Krease

+0

我正在使用java,這裏是代碼... –

回答

0

您對Java中引用和變量的工作原理有一些基本的誤解,一般來說,只有當您看到new這個關鍵字時,纔會創建一個新對象,如new ConcurrentSkipListSet()(有些特殊情況下如何創建對象而不會看到一些new關鍵字,但我不知道你可以忽略這一點)

從一個變量到另一個變量的所有賦值都不會創建新的對象,而是將該變量賦值給與其他變量相同的對象。相同的對象

您有此代碼例如:

while (ir.hasNext()) { 
     ConcurrentSkipListSet b = new ConcurrentSkipListSet(); 
     b = a; // 'b' now refers to the same object as 'a'. 
     ... 
    } 

這是完整的無意義的。您創建一個新列表並將它放在下一行,因爲現在您將參考b指向參考a指向的同一對象。

這就是爲什麼你只有效使用您先創建所有的代碼清單對象:

ConcurrentSkipListSet a = new ConcurrentSkipListSet(); 

大同小異與二維數組。您只創建了一個,將其分配給l,並在代碼後面指出g指向l指向的同一個陣列。之後,您複製了一些值,但實際上您將值複製到了SAME數組對象。這完全是無意義的。在for循環的頂部推System.out.println(this.g[2][1]);行,我敢打賭你會感到驚訝。

看看this SO answer哪@RC。張貼在他的評論。它解決了你誤解的根源。

+0

@ Fabian Barney我應該更加認真地對待我的基礎知識......非常感謝! –