2011-12-07 48 views
1

我遇到了一個問題,我試圖通過存儲餐館對象的arraylist迭代,但循環只能通過五個元素中的三個。循環不遍歷整個ArrayList

我創建的測試方法來說明:

public void testLoop() { 
     ArrayList<Eatery> test = new ArrayList<Eatery>(); 
     test = eateriesListDefault; 
     for(Eatery e : test) { 
      MyLog.e(TAG, "Name: " + e.getName()); 
     } 
     for (int i = 0; i < eateriesListDefault.size(); i++) { 
      MyLog.e(TAG, "Name " + test.get(i).getName()); 
      test.remove(i); 
     } 
     for(Eatery e : test) { 
      MyLog.e(TAG, "Name " + e.getName()); 
     } 
    } 

在這裏測試將在它5個餐館對象。第一個循環成功打印5個名稱中的5個。 第二個循環僅刪除餐館中的3個,因此最後一個循環打印兩個名稱。

我已經到位,第二循環的使用

for(Eatery e : eateriesListDefault) { 
      MyLog.e(TAG, "Name: " + e.getName()); 
      test.remove(e); 
} 

試過,但我得到一個併發訪問錯誤。

有誰知道我在做什麼錯?

+2

首先,你不應該嘗試從集合中刪除值時使用'foreach'循環。這是您的併發訪問錯誤的原因。請參閱[本頁](http://docs.oracle.com/javase/tutorial/collections/interfaces/collection.html)。你還可以解釋爲什麼你發出一個'新的ArrayList'調用只在下一行創建一個賦值? – Grambot

+0

我們能否看到eateriesListDefault會是什麼樣子?或許不是「for(Eatery e:test)」作爲第一個循環,您應該嘗試模仿第二個循環,以便將蘋果與蘋果進行比較。我只是想排除任何索引問題。 – dispake

回答

7

你在每個循環迭代中調用eateriesListDefault.size()。與此同時,你打電話給test.remove(i),每次迭代將數組短路一次。你的循環基本上是這樣做的:

  1. I = 0 尺寸= 5 繼續下去

  2. I = 1個 大小= 4 繼續下去

  3. I = 2 大小= 3 繼續前進

  4. i = 3 size = 2 停止

如果你的目標是要打印出數組的第一個元素,然後將其刪除,你也許可以通過這個循環路線:

while(!eateriesListDefault.isEmpty()) { 
    MyLog.e(TAG, "Name " + test.get(0).getName()); 
    test.remove(0); 
} 
+0

+1個不錯的插圖。修正了一個錯字。 –

2

當循環索引不斷增加時,第二個循環會從數組中刪除元素。在第四遍時,你的循環索引是3,但eateriesListDefault.size是2,所以循環退出。

試試這個:

for (Iterator<Eatery> it = test.iterator(); it.hasNext();) { 
    MyLog.e(...) 
    it.remove(); 
} 

迭代器的行爲是不確定的,如果列表以任何方式迭代過程中修改以外致電Iterator.remove()。請參閱Iterator.remove() documentation

另外,您可能需要製作默認列表的副本。你的「test =」語句只是對同一個列表進行新的引用。

test = new ArrayList<Eatery>(eateriesListDefault); 
+1

在擴展說明中:如果考慮循環的工作方式,可以執行多個步驟:第1步,列表大小= 5,刪除元素。第2步,列表大小= 4刪除一個元素。步驟3,循環大小= 3,退出。 – Grambot