6

As I run the following code :

    import java.util.LinkedList;

    class Tester {
      public static void main(String args[]) {
        LinkedList<String> list = new LinkedList<String>();
        list.add(new String("suhail"));
        list.add(new String("gupta"));
        list.add(new String("ghazal"));
        list.add(new String("poetry"));
        list.add(new String("music"));
        list.add(new String("art"));

        try {
            for(String s : list) {
            list.add(0,"art");
            list.remove(6);
            System.out.println(list);
        }
        }catch(Exception exc) {
            exc.printStackTrace();
        }

    }
}

I get an exception that says :

java.util.ConcurrentModificationException
    at java.util.LinkedList$ListItr.checkForComodification(Unknown Source)
    at java.util.LinkedList$ListItr.next(Unknown Source)
    at Tester.main(Tester.java:14)

Why am I getting this exception ?

Edit : tmpList is a LinkedList whose each node contains an object of type DepConfAttr. I am sorting the tmpList on the basis of memory (Highest memory first), which is one of the attribute of the object of DepConfAttr.

The above code reflected what I am trying to achieve through the following code

int size = tmpList.size();
        int elementBC = 0; // element being checked
        int startIndex = 1;
        for (DepConfAttr dca : tmpList) {
            long maxMem = dca.getMemory(); // Let this be the maximum memory
            for(int i = startIndex ; i < size ; i++) {
                DepConfAttr dcaTmp = tmpList.get(i);
                if(maxMem < dcaTmp.getMemory()) {
                    tmpList.add(elementBC, dcaTmp);
                    tmpList.remove(i+1);
                    maxMem = tmpList.get(elementBC).getMemory();                        
                }
            }
            elementBC++;
            startIndex++;
            size--;
        }
6
  • 2
    Don't remove while iterating. Commented Aug 26, 2013 at 9:07
  • 2
    What exactly are you trying to do? I don't see you using s anywhere in the loop? Commented Aug 26, 2013 at 9:08
  • You are adding and removing while iterating. Thus you have a concurrent modification. To make sense of what you should do instead you have to working what you are really trying to do which is not clear. Commented Aug 26, 2013 at 9:09
  • @Eng.Fouad I still get the same exception Commented Aug 26, 2013 at 9:09
  • 1
    @SuhailGupta. Well, also don't add while iterating. I know that wouldn't help. But you should first tell us the purpose of your code? Are you trying to replace all elements with art? Commented Aug 26, 2013 at 9:10

7 Answers 7

13

Why am I getting this exception ?

You're removing an item from the list other than via the iterator, while iterating over it. You're also adding to the list while you're iterating over it.

It's not really clear what you're trying to achieve here, but other than with the concurrent collections, you'll always get an exception when you try to do that.

One common fix to this is to create a copy of the list first and iterate over that, modifying the original as you go.

Sign up to request clarification or add additional context in comments.

2 Comments

Exact answer for this question
@SuhailGupta: There are much better ways of sorting - use Collections.sort with a custom comparator, but preferably not using a LinkedList. (Copy it to an ArrayList first.)
2

When you iterate through a list, you can't remove items from it. Doing so causes the exception.

Do:

int size = list.size();
for (int i = 0 ; i< size ; i++) {
   list.add(0,"art");
   list.remove(6);
   System.out.println(list);
}

Comments

1

The problem is that you're directly modifying the List while an Iterator is trying to run over it. The next time you tell the Iterator to iterate (implicitly, in the for loop), it notices the List has changed out from under it and throws the exception.

Instead, if you need to modify the list while traversing it, grab the Iterator explicitly and use it:

List<String> list = ....
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    String s = iterator.next(); // must be called before you can call iterator.remove()
    iterator.remove();
}

You still can't insert into the List while this is going on, and this won't let you remove arbitrary elements, just the current one.

1 Comment

He is not removing the current element, but the element at index 6. So, this won't help. Frankly, the question is not very clear.
0

The problem is making a change to the list while using an implicit Iterator over it. For the quoted code, the simplest solution is to not use the Iterator at all:

for(int i=0; i<list.size(); i++) {
  list.add(0,"art");
  list.remove(6);
  System.out.println(list);
}

You may need to post more realistic code to get advice for the best solution. If you want to possibly remove the current item while iterating over the list, use an explicit Iterator loop, and use the Iterator's remove() method. In other cases, the best solution is to form a plan for the changes inside the loop, but execute it afterwards. For example, during a loop over list build a removeList containing a list of indexes of elements you want to remove. In a separate loop over removeList, remove those elements from list.

Comments

0

Because you are concurrently (simultaneously) modifying and iterating through a collection. Java doesn't like this

Since you don't actually use s, you can use a standard for loop

for(int i=0; i< list.size(); i++) {
      list.add(0,"art");
      list.remove(6);
      System.out.println(list);
}

Comments

0

The ConcurrentModificationException is thrown when iterating through the list and at the same time when you are trying to modify (add/remove) the contents of the list either through another thread or in a loop.

You can try using ConcurrentLinkedQueue or as John stated do a copy and modify the original in iteration.

Queue<String> list = new ConcurrentLinkedQueue<String>();

list.add("suhail");
list.add("gupta");
list.add("ghazal");
list.add("poetry");
list.add("music");
list.add("art");

int size = list.size();

for(int i = 0; i < size; i++){
    list.add("art");
    list.remove("art");
    System.out.println(list);
}

Comments

-1

You would need to use iterator explicitly for that to work. Example:

 Iterator<String> iter = li.iterator();
   while(iter.hasNext()){
    if(iter.next().equalsIgnoreCase("some value"))
      iter.remove();
    }
   }

More info here: http://www.coderanch.com/t/233932/threads/java/deal-Concurrent-Modification-Exception but just google the exception and you will find lots of examples.

4 Comments

You're using concurrent collections - that's what's making the difference here, not the iterator.
Its just one of the examples, both of the examples are using iterator.
Both of your examples are using concurrent collections. Both would fail if you used non-concurrent collections. Note that the enhanced for loop uses iterators under the hood too.
And now it wouldn't be covered by what the OP's attempting to do, as he's not removing "the current" item, he's removing the element at index 6.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.