2013-02-24 253 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"));