2013-02-24 165 views
-1

我有一個小問題。我試圖從ArrayList中刪除一個對象,但不會發生更改。ArrayList:在for循環中刪除對象

下面是代碼示例:

List<Room> rooms = new CopyOnWriteArrayList<Room>(); 

    rooms.addAll(fp.getRooms()); 
    int counter = 1; 

    for(Room r: rooms){ 
     for(Square s: r.getDoor()){ 
      r.getDoor().remove(s); 
      String name = String.valueOf(fp.getRooms().size() + counter); 
      Room doorRoom = new Room(name, false, s, s); 
      rooms.add(doorRoom); 
      counter++; 
     } 
    } 

    fp.setRooms(rooms); 

我試圖刪除對象s,並用新的對象doorRoom更換。

輸出:

 
First> [S: 11:7; true, S: 11:15; true, S: 11:20; true] 
Second> [S: 11:7; true, S: 11:15; true, S: 11:20; true] 

而且我很期待:

 
First> [S: 11:7; true, S: 11:15; true, S: 11:20; true] 
Second> [S: 11:15; true, S: 11:20; true] 

的等等...

問題是什麼?

謝謝,我很樂意收到您的回覆!

+1

你可能想告訴我們,正是你所看到的發生,哪些是你希望在您認爲它沒有做什麼,你認爲它應該做的每一點發生。 (事實上​​,只要這樣做,你可能會自己找出問題,但是如果不是,我們有一個出發點來幫助你。) – Wormbo 2013-02-24 20:09:26

+0

可能是迭代過程中混合添加/刪除的問題。但是我找不到解釋這是否合法的文檔。 – djechlin 2013-02-24 20:11:04

+0

@djechlin我認爲,但http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/CopyOnWriteArrayList.html聲明列表永遠不會拋出ConcurrentModificationException。儘管OP在添加新房間實例時從未刪除「r」房間。 – mabi 2013-02-24 20:14:28

回答

1

好吧,有兩個問題與您的代碼:

  1. 你是不是真正刪除 「R」。您只能從與「r」相關的門上移除一個正方形。
  2. 您無法刪除擴展for循環內的對象。您應該爲此使用迭代器(請參閱:Calling remove in foreach loop in Java),我不完全確定是否可以在迭代對象時將對象添加到集合中(請參見Java: adding elements to a collection during iteration)。

嘗試下面的鏈接的描述來解決問題

+0

實際上,'CopyOnWriteArrayList'的迭代器在列表的快照上工作。 API文檔明確指出。 – Wormbo 2013-02-24 20:19:42

0

for (Square s: r.getDoor())使用迭代器內部,並在遍歷它,你不能改變一個ArrayList。如果你使用了一個循環變量(for (int i = 0;...)),它會起作用,但這不是一個好主意,因爲列表的長度會改變,並且一些對象會被留在循環之外。

你應該記住要刪除的對象,然後在循環之後刪除。

0

實際上,您可以在迭代時修改列表,但不能直接(它會拋出ConcurrentModificationException)。只需使用ListIterator即可。例如:

List<String> l = new ArrayList<>(); 
    l.add("a"); 
    l.add("b"); 
    l.add("c"); 

    for (ListIterator<String> it = l.listIterator(); it.hasNext();) { 
     String s = it.next(); 
     if ("b".equals(s)) { 
      it.remove(); 
      it.add("r"); 
     } 
    } 

    assertFalse(l.contains("b")); 
    assertTrue(l.contains("r"));