-1

I have a little problem. I'm trying to remove an object from ArrayList, but the change doesn't occur.

Here is the code sample:

    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);

I'm trying to remove the object s and replace it with a new object doorRoom.

Output:

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]

And I'm expecting:

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

an so on...

What is the problem?

Thank you and I'll be glad to receive your response!

Windle
  • 1,326
  • 1
  • 14
  • 32
uccie
  • 183
  • 2
  • 9
  • 1
    You might want to tell us what exactly you see happening and what you expected to happen at every point where you think it's not doing what you thought it should do. (In fact, just by doing that, you probably figure out the problem on your own, but if not we have a starting point for helping you.) – Wormbo Feb 24 '13 at 20:09
  • Probably a problem with mixing add/remove in the middle of iterating. But I can't find the documentation that explains whether this is legal. – djechlin Feb 24 '13 at 20:11
  • @djechlin what I thought, but http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/CopyOnWriteArrayList.html states the list will never throw ConcurrentModificationException. Though the OP never actually removes the "r" Room while adding new Room instances. – mabi Feb 24 '13 at 20:14
  • Now I'm confused. You want to "replace" the Room instance, but that means removing a Room instance after adding a new one. You're not replacing the Room instance if you're removing a Square object instead. So can you describe what you're actually trying to achieve? – mabi Feb 24 '13 at 20:42
  • I fixed it! Thank you. You can close the topic. Row 6: r.getSquares().remove(s). – uccie Feb 24 '13 at 20:50
  • Are you trying to remove `r` from `rooms` list? If so, I'm not seeing on your code `rooms.remove(r)`. – JoaaoVerona Feb 24 '13 at 20:11
  • Sorry! Object "s" from r.getDoor() list. – uccie Feb 24 '13 at 20:13
  • Well, have you checked the `hashCode()` and `equals(obj)` methods of your Square object? The list verifies if the object to be removed equals to list contents using these methods. – JoaaoVerona Feb 24 '13 at 20:15

3 Answers3

1

Ok, there are two problems with your code:

  1. You are not actually removing "r". You only remove a square from the door that is associated with "r".
  2. You cannot remove an object inside an extended for loop. You should use an iterator for this (see: Calling remove in foreach loop in Java) and I'm not totally sure whether you can add an object to a collection while iterating over it (see Java: adding elements to a collection during iteration).

Try following the descriptions in the links to resolve your problem

Community
  • 1
  • 1
fachammer
  • 181
  • 4
  • Actually, a `CopyOnWriteArrayList`'s iterator works on a snapshot of the list. The API docs explicitly state that. – Wormbo Feb 24 '13 at 20:19
0

for (Square s: r.getDoor()) uses an iterator internally and you can't change an ArrayList while iterating over it. It would work if you used a loop variable (for (int i = 0;...)), but that's not a good idea as the list's length would change and some of the objects would be left unchecked out of the loop.

You should just remember the objects to be removed and then removed after the loop.

j0ntech
  • 1,158
  • 3
  • 13
  • 27
0

Actually you can modify Lists while iterating, but not directly (it will throw ConcurrentModificationException). Just use ListIterator to do it. Ex:

    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"));
Marek Piechut
  • 558
  • 4
  • 9