简体   繁体   中英

removing duplicates linkedlist concurrent modification exception

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.

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

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 (eg 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.

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.

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 (eg ConcurrentLinkedQueue - but see then answers at Lock-Free Concurrent Linked List in Java for warnings about this)
  2. Switch to a set structure, eg 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, ie 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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM