2

I have a list I need to iterate over and delete certain items. I can't use an iterator because I need to call methods for each item (such as ls.getStatus()) which doesn't work with an iterator. If ls.getStatus() == 0 I need to delete that item. How can I avoid the ConcurrentModificationException?

for (MyList ls : list) {
    if (ls.getStatus() == 0) {
        ls.run();
        list.remove();
    } else {
        ls.create();
    }
}

Thanks

A.H.
  • 63,967
  • 15
  • 92
  • 126
user1212520
  • 501
  • 1
  • 5
  • 15

3 Answers3

5

Why don't you think you can use an iterator?

Iterator<MyList> i = list.iterator();
while (i.hasNext()) {
    MyList ls = i.next();

    //... all your other code which uses ls...

    i.remove();
}

This approach is also likely to be faster, since using iterator.remove() avoids having to search for the item in the list which is necessary with list.remove(item).

dty
  • 18,795
  • 6
  • 56
  • 82
  • If ls is an object in the list I got an error saying I can't call methods from the object class such as ls.getStatus? – user1212520 Feb 19 '12 at 19:46
  • 2
    @user1212520: because you're not using a *generic* iterator. See dty's example above. But your basic assumption -- that you can't use an iterator is wrong. Period. – Hovercraft Full Of Eels Feb 19 '12 at 19:48
  • The problem is that remove operation can invalidate the iterator. – Trismegistos Feb 19 '12 at 19:49
  • @Trismegistos: Where does it say, that calling `remove` invalidates the iterator? "Removes from the underlying collection the last element returned by this iterator (optional operation). *This method can be called only once per call to next().*" (emphasis mine) clearly suggests, that remove is designed to be called during iteration without invalidating the iterator. – Dirk Feb 19 '12 at 20:08
  • @Dirk If it is implemented according to documentation. I custom list (which MyList is) it might not have been implemented like that although it should. It can also throw UnsupportedOperation exception. – Trismegistos Feb 19 '12 at 20:13
  • @Trismegistos - you have a point. Though, since the OP himself considered using `Iterator.remove()` (which wouldn't work for him for other reasons), I find it legit to assume, that the iterator provided by whatever kind of list `list` is, *will* provide support for `remove`. – Dirk Feb 19 '12 at 20:20
  • First, none of these operations is being done on `MyList`. `MyList` is the type of the content of the list being iterated. Secondly, even if that were not the case, you cannot possibly know what the behaviour of `MyList` is - it might be a simple subclass of an existing JDK List. And thirdly, if a custom list (and its custom iterator) did behave as you suggest, it would be in violation of the contract of `Iterator`. That's a whole lot of assumptions. – dty Feb 19 '12 at 20:39
  • @Dty this is called programmer experience. – Trismegistos Feb 20 '12 at 17:23
  • Hey, I don't want to get into a pissing match with you, but I've been programming for 30 years and have been using Java since it was doing the rounds in academic circles before its first public release - and with all that experience, I don't share your concerns about malfunctioning iterators. Certainly not enough to consider them while deciding which kind of loop construct to use and whether to use `iterator.remove()` or attempt some other, less clear/performant approach. – dty Feb 20 '12 at 21:24
1

You can use an iterator, but only by abandoning the enhanced for loop:

for (Iterator<MyList> iterator = list.iterator(); iterator.hasNext(); ) {
    MyList ls = iterator.next();
    if (ls.getStatus() == 0) {
        lo.run(zo);
        iterator.remove();
    } else {
        ls.create();
    }
}

Of course, that assumes that list refers to a type which supports the remove operation.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
-1

In case your iterator does not support remove operation you could use following algorithm:

In first step you can iterate over list creating list of indices of elements to be deleted. Next step would be iterating over list of indices backward and deleting elements by index.

Trismegistos
  • 3,821
  • 2
  • 24
  • 41