java.util.ConcurrentModificationException в цикле For

Я пытаюсь запрограммировать программное обеспечение для обмена мгновенными сообщениями, я хочу, чтобы пользователь оставил разговор и сказал своему партнеру, что он ушел... Вместо этого я предпочитаю использовать цикл for Iterator, искать всех пользователей и получать пользователя, который просит выйти и удалить его... вот так:

   for(Clientuser Cu: EIQserver.OnlineusersList)
          if(Cu.ID.equals(thsisUser.ID)) // find the user who ask to leave 
          {
          Omsg.setBody("@@!&$$$$@@@####$$$$"); //code means : clien! ur parter leaves...
                 sendMessage(Omsg); // sed message to thje partner with that code
                 EIQserver.OnlineusersList.remove(Cu);// remove the partner
                EIQserver.COUNTER--;// decrease counter.

          }

Я получаю исключение: java.util.ConcurrentModificationException

Я использовал итераторы, и чтобы избавиться от этого исключения, я преобразовал его в for, но то же самое исключение все еще появляется!! как я могу избавиться от этого исключения?


person EsmaeelQash    schedule 31.10.2013    source источник
comment
Вы не можете удалить что-то из списка, который вы просматриваете.   -  person Trick    schedule 31.10.2013
comment
@Trick, если вы не удалите его с помощью того же итератора, который вы используете в цикле, или вы не используете коллекцию, которая его поддерживает, например CopyOnWriteArrayList.   -  person aalku    schedule 31.10.2013
comment
Вы обязательно должны прочитать это (не ответ): oracle.com/technetwork /java/codeconventions-135099.html#367   -  person aalku    schedule 31.10.2013
comment
Истинный. Кстати, @EsmaeelQash, попробуйте следовать стандартам кодирования Java (соглашениям об именах). Если вы когда-нибудь передадите свой код, это создаст боль для вашего подписчика :)   -  person Trick    schedule 31.10.2013
comment
Я отредактирую вопрос, чтобы следовать соглашениям об именах...   -  person aalku    schedule 31.10.2013
comment
Нет необходимости делать это сейчас :) Просто имейте в виду ваши будущие усилия.   -  person Trick    schedule 31.10.2013


Ответы (5)


Используйте итератор вместо цикла. Например:

Iterator<Clientuser> iterator = EIQserver.OnlineusersList.iterator();
while (iterator.hasNext()) {
    Clientuser next = iterator.next();
    if(next.ID.equals(thsisUser.ID)) {
        Omsg.setBody("@@!&$$$$@@@####$$$$"); 
        sendMessage(Omsg); 
        iterator.remove();// remove the partner
    }
}
person Konstantin Yovkov    schedule 31.10.2013
comment
спасибо, kocko, но iterator.remove() удаляет объект из EIQserver.OnlineusersList?? - person EsmaeelQash; 31.10.2013
comment
Да, он удаляет последний выбранный объект из списка. - person Konstantin Yovkov; 31.10.2013

Линия разлома: EIQserver.OnlineusersList.remove(Cu);

Вы можете удалять только элементы из коллекции, которая повторяется через объект Iterator, который вы используете для итерации.

for (Iterator<Clientuser> it = EIQserver.OnlineusersList.iterator(); it.hasNext();)
{
    Clientuser cu = it.next();
    if (!cu.ID.equals(thsisUser.ID))
        continue;
    // other code
    it.remove();
}
person afk5min    schedule 31.10.2013

Используйте Iterator, чтобы сделать что-то со списком в цикле:

Iterator<Clientuser> iter = EIQserver.OnlineuserList.iterator();
for(;iter.hasNext();) {
    Clientuser Cu = iterator.next();
    if(Cu.ID.equals(thsisUser.ID)) {
        Omsg.setBody("@@!&$$$$@@@####$$$$"); 
        sendMessage(Omsg); 
        iterator.remove(next);
    }
}
person SeniorJD    schedule 31.10.2013

Одним из возможных решений также является преобразование коллекции в HashMap, сохранение идентификаторов для удаления, а затем удаление их из HashMap.

Collection<Integer> removeIds = new ArrayList<Integer>();
Map<Integer,ClientUser> all = new HashMap<Integer,ClientUser>();

for(Clientuser Cu: EIQserver.OnlineusersList) {
all.put(cu.ID,Cu);
      if(Cu.ID.equals(thsisUser.ID)) // find the user who ask to leave 
      {
      Omsg.setBody("@@!&$$$$@@@####$$$$"); //code means : clien! ur parter leaves...
             sendMessage(Omsg); // sed message to thje partner with that code
            EIQserver.COUNTER--;// decrease counter.
    removeIds.add(Cu.ID);

      }
}
person Trick    schedule 31.10.2013

Поскольку вы повторяете класс коллекции EIQserver, вы не можете удалить элемент из того же класса. Используйте другую коллекцию для итерации и удалите элемент из класса EIQserver.

 List temp = ListofEIQserverobject;
  for(Clientuser Cu: temp.OnlineusersList){
    ..... your code then 
      EIQserver.OnlineusersList.remove(Cu);
    }
person Debabrata    schedule 31.10.2013
comment
Для этого temp должен быть копией списка, а не ссылкой на себя. - person aalku; 31.10.2013