开发者

Is there an accepted best practice in Java for deleting a list element while iterating over the list?

I'm finding conflicting advice over the best way to avoid a ConcurrentModificationException while doing this:

    List<Apple开发者_如何学Python> Apples = appleCart.getApples();
    for (Apple apple : Apples)
    {
        delete(apple);
    }

I'm leaning towards using an Iterator in place of a List and calling its remove method.

Does that make the most sense here?


Yes, use an Iterator. Then you could use its remove method.

  for (Iterator<Apple> appleIterator = Apples.iterator(); appleIterator.hasNext();) {
     Apple apple = appleIterator.next();
     if (apple.isTart()) {
        appleIterator.remove();
     }
  }
}


If you're getting a ConcurrentModificationException, you likely have multiple threads.

So the full answer includes both using Iterator.remove() and synchronizing access to the collection.

For example (where lock is synchronized on by all threads that may modify the list):

synchronized ( lock ) {
   List<Apple> apples = appleCart.getApples();
   for ( Iterator<Apple> it = apples.iterator(); it.hasNext(); )
   {
      Apple a = it.next(); 
      if ( a.hasWorm() ) {
         it.remove();
      }
   }
}


List<Apple> apples = appleCart.getApples();
for (Iterator<Apple> appleIterator = apples.iterator(); appleIterator.hasNext();)
{
   Apple apple = appleIterator.next();
   if ( apple.isYucky() ) {
     appleIterator.remove();
   }
}


You could keep a list of items to remove and then remove them after the loop:

List<Apple> apples = appleCart.getApples();
List<Apple> badApples = new ArrayList<Apple>();
for (Apple apple : apples) {
    if (apple.isBad()) {
        badApples.add(apple);
    } else {

    eat(apple);
}

apples.removeAll(badApples);


Since Java 8 you can now do this: apples.removeIf(apple -> apple.equals(this))

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜