1

I have a linkedlist where each element has key and value(ArrayList<dataStructure>). I want to merge the elements having same key.

    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();
                    }
                }
            }
        }
    }

Though I am using the iterators remove methog getting a java.util.ConcurrentModificationException. What should be changed to get rid of this.

vjk
  • 2,163
  • 6
  • 28
  • 42
  • 1
    why not `LinkedHashSet` ? – jmj Aug 13 '13 at 16:41
  • possible duplicate of [Efficient equivalent for removing elements while iterating the Collection](http://stackoverflow.com/questions/223918/efficient-equivalent-for-removing-elements-while-iterating-the-collection) – Juned Ahsan Aug 13 '13 at 16:44
  • @JunedAhsan, respectfully, disagree. vjk is using Iterator.remove(), his situation is more complex. It's closer to this: http://stackoverflow.com/questions/9268399/java-multiple-iterators-on-a-set-removing-proper-subsets-and-concurrentmodific – Taylor Aug 13 '13 at 16:59
  • @Taylor Agreed, thats why 'possible' used and not 'exact' ;-) – Juned Ahsan Aug 13 '13 at 17:01

5 Answers5

2

You remove element with one of your iterators, thus the second of them does not know about this removal and ConcurrentModificationException is thrown

BTW:

you should consider using some multimap in place of list that is having key-values pairs

dantuch
  • 9,123
  • 6
  • 45
  • 68
1

Both your iterators are traversing the linked list

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

probably iItr should be for the inner array list?

UPDATE Scratch above answer I misread the question. The challenge though is that you have two iterators traversing the list, so while you use one iterator's remove() method, the other still detects the concurrent modification.

Normally, to remove duplicates from a list, you can just run them through a Set (e.g. a HashSet) but that won't work for you as it's only key duplication, not the entire member of the list.

I'd take an approach where I try to find and capture the duplicated keys and their values in a separate list and then merge in and remove the duplicates as a separate step.

Taylor
  • 3,942
  • 2
  • 20
  • 33
1

Add the elements you want to remove in another List and then loop in that list at the end to remove these elements.

Alternatively, use a Map/Set.

Matthieu
  • 2,736
  • 4
  • 57
  • 87
0

The problem is that when you use the iItr.remove() it modifies the list, which iItr is happy with because it knows what changed, but oItr isn't. There are three possible solutions to this that I can see:

  1. Switch to a concurrent list (e.g. ConcurrentLinkedQueue - but see then answers at Lock-Free Concurrent Linked List in Java for warnings about this)
  2. Switch to a set structure, e.g. TreeSet, which will keep your items unique automatically (but won't preserve their order)
  3. Make sure you don't use the other iterator after removing from one of them -- you could do this by switching which element you are removing, i.e. change iItr.remove() to:

     oItr.remove();
     break;
    

This would cause the first instance of each key to be removed, rather than subsequent ones, which might not be the behaviour you want -- in that case you could try iterating over the lists backwards.

Community
  • 1
  • 1
Jules
  • 14,841
  • 9
  • 83
  • 130
0

Will this work?

 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;
                    }
                }
            }
        }
    }
vjk
  • 2,163
  • 6
  • 28
  • 42