2013-08-13 3 views
1

У меня есть связанный список, где каждый элемент имеет ключ и значение (ArrayList<dataStructure>). Я хочу объединить элементы, имеющие один и тот же ключ.удаление дубликатов связанного списка исключение параллельной модификации

Iterator<CElem> oItr = linkedList.iterator(); 
    { 
     while (oItr.hasNext()) 
     { 
      CElem outer = oItr.next();    
      Iterator<CElem> iItr = linkedList.iterator(); 
      { 
       while (iItr.hasNext()) 
       { 
        CElem inner = iItr.next(); 
        if (outer.equals(inner)) 
         continue; 

        if (outer.getKey().equals(inner.getKey())) 
        { 
         outer.getValues().addAll(inner.getValues()); 
         iItr.remove(); 
        } 
       } 
      } 
     } 
    } 

Хотя я использую итераторы удалить methog получение java.util.ConcurrentModificationException. Что нужно изменить, чтобы избавиться от этого.

+1

Почему не 'LinkedHashSet'? –

+0

Возможный дубликат [Эффективный эквивалент для удаления элементов при повторении коллекции] (http://stackoverflow.com/questions/223918/efficient-equivalent-for-removing-elements-while-iterating-the-collection) –

+0

@JunedAhsan, с уважением, не согласен. vjk использует Iterator.remove(), его ситуация сложнее. Это ближе к этому: http://stackoverflow.com/questions/9268399/java-multiple-iterators-on-a-set-removing-proper-subsets-and-concurrentmodific – Taylor

ответ

0

Будет ли это работать?

Iterator<CElem> oItr = linkedList.iterator(); 
    { 
     while (oItr.hasNext()) 
     { 
      CElem outer = oItr.next();    
      Iterator<CElem> iItr = linkedList.iterator(); 
      { 
       while (iItr.hasNext()) 
       { 
        CElem inner = iItr.next(); 
        if (outer.equals(inner)) 
         continue; 

        if (outer.getKey().equals(inner.getKey())) 
        { 
         inner.getValues().addAll(outer.getValues()); 
         outer.remove(); 
         break; 
        } 
       } 
      } 
     } 
    } 
1

Оба ваших итераторы обход связанного списка

Iterator<CElem> oItr = linkedList.iterator(); 
.... 
Iterator<CElem> iItr = linkedList.iterator(); 

вероятно iItr должен быть для внутреннего списка массива?

ОБНОВЛЕНИЕ Царапина выше ответ Я неправильно понял вопрос. Проблема состоит в том, что у вас есть два итератора, проходящих по списку, поэтому, хотя вы используете один метод remove() итератора, другой все еще обнаруживает одновременную модификацию.

Обычно, чтобы удалить дубликаты из списка, вы можете просто запустить их через Set (например, HashSet), но это не сработает для вас, поскольку это всего лишь дублирование ключей, а не весь член списка.

Я попытался бы найти и захватить дублированные ключи и их значения в отдельном списке, а затем объединить и удалить дубликаты в качестве отдельного шага.

2

Вы удаляете элемент с одним из итераторов, поэтому второй из них не знают об этом удалении и ConcurrentModificationException бросают

КСТАТИ:

Вы должны рассмотреть использование some multimap вместо списка, имеющие ключевые значения пар

0

проблема заключается в том, что при использовании iItr.remove() он изменяет список, который iItr доволен, потому что он знает, что изменилось, но oItr нет. Есть три возможных решения это, что я могу видеть:

  1. коммутатора к одновременному списка (например, ConcurrentLinkedQueue - но видеть то ответы на Lock-Free Concurrent Linked List in Java для предупреждения об этом)
  2. Переключение в заданной структуре, например TreeSet, который автоматически сохранит ваши позиции (но не сохранит их порядок)
  3. Убедитесь, что вы не используете другой итератор после удаления с одного из них - вы можете сделать это, переключив этот элемент удаление, т.е. изменение iItr.remove() на:

    oItr.remove(); 
    break; 
    

Это может привести первый экземпляр каждого ключа должны быть удалены, а не последующие, которые не могли бы быть поведение, которое вы хотите - в этом случае вы могли бы повторите попытку по спискам назад.

1

Добавьте элементы, которые вы хотите удалить в другом списке, а затем зациклируйте в этом списке в конце, чтобы удалить эти элементы.

В качестве альтернативы используйте карту/набор.