Помощь ConcurrentModificationException в итераторе - PullRequest
1 голос
/ 02 апреля 2012

Я получаю ConcurrentModificationException в следующем фрагменте кода

, когда я запускаю код, все прошло нормально, но внезапно выдает исключение, я думаю, это из-за изменения списка, но я 'Я не уверен, как это исправить

if (myRulesIncr!=null)
{
    Iterator itReceivedRules = myRulesIncr.iterator();
    while (itReceivedRules.hasNext())
    {
      RuleModel currentReceived = (RuleModel) itReceivedRules.next();
      if (receivedRulesExisting!=null)
      {
        Iterator itReceivedRulesExisting = receivedRulesExisting.iterator();
        while (itReceivedRulesExisting.hasNext())
        {
            RuleModel currentExisting = (RuleModel) itReceivedRulesExisting.next();

            if(currentExisting.getRuleId().equals(currentReceived.getRuleId()))
            {
                //TODO:replace the rule else add it.
                if(currentReceived.getStatus()!="D")
                { 
                    //replace the existing rule with the new one
                    receivedRulesExisting.remove(currentExisting);
                    receivedRulesExisting.add(currentReceived);
                } 
                else
                {
                    receivedRulesExisting.remove(currentExisting); 
                }
            }
            else
            {
                //Add the new rule to the existing rules
                receivedRulesExisting.add(currentReceived);
            }
        }
      }
    }
}

Пожалуйста, помогите мне в этом.

Ответы [ 2 ]

4 голосов
/ 02 апреля 2012

ConcurrentModificationException генерируется, когда итеративная коллекция модифицируется извне, т.е. не через итератор.Поэтому вам нужно использовать Iterator.remove(), чтобы избежать этого исключения.Более того, вместо добавления непосредственно в коллекцию во время итерации по ней, сохраните элементы, которые нужно добавить, в отдельную коллекцию, а затем добавьте их впоследствии:

  List<RuleModel> toBeAdded = new ArrayList<RuleModel>();

  if(currentReceived.getStatus()!="D")
  { 
      //replace the existing rule with the new one
      itReceivedRulesExisting.remove();
      toBeAdded.add(currentReceived);
  } 
  else
  {
      itReceivedRulesExisting.remove(); 
  }

  ...
  // after the loop terminated:
  receivedRulesExisting.addAll(toBeAdded);

Обратите внимание, что я использовал универсальную коллекцию - этоЖелательно сделать так, чтобы обеспечить безопасность типов и избавиться от даункастов, например, так:

Collection<RuleModel> myRulesIncr = ...
...
Iterator<RuleModel> itReceivedRules = myRulesIncr.iterator();
...
RuleModel currentReceived = itReceivedRules.next();
0 голосов
/ 02 апреля 2012

Это в многопоточной среде? Если да, используйте потокобезопасные коллекции. CopyOnWriteArrayList или Collections.synchronizedList

...