Weird Java Concurrent modification exception example

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
6
down vote

favorite












If we write like this, there is a concurrent modification exception :



public static void main(String... args) 
List<String> listOfBooks = new ArrayList<>();
listOfBooks.add("Programming Pearls");
listOfBooks.add("Clean Code");
listOfBooks.add("Effective Java");
listOfBooks.add("Code Complete");

System.err.println("Before deleting : " + listOfBooks);
for (String book : listOfBooks)
if (book.contains("Code"))
listOfBooks.remove(book);


System.err.println("After deleting : " + listOfBooks);



On the other hand, if we write like this, there is NO concurrent modification exception !
Notice that code is exact the same, except the strings for compare, in first example it is a Code, and in second it is a Java



public static void main(String... args) 
List<String> listOfBooks = new ArrayList<>();
listOfBooks.add("Programming Pearls");
listOfBooks.add("Clean Code");
listOfBooks.add("Effective Java");
listOfBooks.add("Code Complete");

System.err.println("Before deleting : " + listOfBooks);
for (String book : listOfBooks)
if (book.contains("Java"))
listOfBooks.remove(book);


System.err.println("After deleting : " + listOfBooks);



I'm using Netbeans 8.2, Windows 7 32bit, with JDK 1.8.0_131
What's wrong ?










share|improve this question

























    up vote
    6
    down vote

    favorite












    If we write like this, there is a concurrent modification exception :



    public static void main(String... args) 
    List<String> listOfBooks = new ArrayList<>();
    listOfBooks.add("Programming Pearls");
    listOfBooks.add("Clean Code");
    listOfBooks.add("Effective Java");
    listOfBooks.add("Code Complete");

    System.err.println("Before deleting : " + listOfBooks);
    for (String book : listOfBooks)
    if (book.contains("Code"))
    listOfBooks.remove(book);


    System.err.println("After deleting : " + listOfBooks);



    On the other hand, if we write like this, there is NO concurrent modification exception !
    Notice that code is exact the same, except the strings for compare, in first example it is a Code, and in second it is a Java



    public static void main(String... args) 
    List<String> listOfBooks = new ArrayList<>();
    listOfBooks.add("Programming Pearls");
    listOfBooks.add("Clean Code");
    listOfBooks.add("Effective Java");
    listOfBooks.add("Code Complete");

    System.err.println("Before deleting : " + listOfBooks);
    for (String book : listOfBooks)
    if (book.contains("Java"))
    listOfBooks.remove(book);


    System.err.println("After deleting : " + listOfBooks);



    I'm using Netbeans 8.2, Windows 7 32bit, with JDK 1.8.0_131
    What's wrong ?










    share|improve this question























      up vote
      6
      down vote

      favorite









      up vote
      6
      down vote

      favorite











      If we write like this, there is a concurrent modification exception :



      public static void main(String... args) 
      List<String> listOfBooks = new ArrayList<>();
      listOfBooks.add("Programming Pearls");
      listOfBooks.add("Clean Code");
      listOfBooks.add("Effective Java");
      listOfBooks.add("Code Complete");

      System.err.println("Before deleting : " + listOfBooks);
      for (String book : listOfBooks)
      if (book.contains("Code"))
      listOfBooks.remove(book);


      System.err.println("After deleting : " + listOfBooks);



      On the other hand, if we write like this, there is NO concurrent modification exception !
      Notice that code is exact the same, except the strings for compare, in first example it is a Code, and in second it is a Java



      public static void main(String... args) 
      List<String> listOfBooks = new ArrayList<>();
      listOfBooks.add("Programming Pearls");
      listOfBooks.add("Clean Code");
      listOfBooks.add("Effective Java");
      listOfBooks.add("Code Complete");

      System.err.println("Before deleting : " + listOfBooks);
      for (String book : listOfBooks)
      if (book.contains("Java"))
      listOfBooks.remove(book);


      System.err.println("After deleting : " + listOfBooks);



      I'm using Netbeans 8.2, Windows 7 32bit, with JDK 1.8.0_131
      What's wrong ?










      share|improve this question













      If we write like this, there is a concurrent modification exception :



      public static void main(String... args) 
      List<String> listOfBooks = new ArrayList<>();
      listOfBooks.add("Programming Pearls");
      listOfBooks.add("Clean Code");
      listOfBooks.add("Effective Java");
      listOfBooks.add("Code Complete");

      System.err.println("Before deleting : " + listOfBooks);
      for (String book : listOfBooks)
      if (book.contains("Code"))
      listOfBooks.remove(book);


      System.err.println("After deleting : " + listOfBooks);



      On the other hand, if we write like this, there is NO concurrent modification exception !
      Notice that code is exact the same, except the strings for compare, in first example it is a Code, and in second it is a Java



      public static void main(String... args) 
      List<String> listOfBooks = new ArrayList<>();
      listOfBooks.add("Programming Pearls");
      listOfBooks.add("Clean Code");
      listOfBooks.add("Effective Java");
      listOfBooks.add("Code Complete");

      System.err.println("Before deleting : " + listOfBooks);
      for (String book : listOfBooks)
      if (book.contains("Java"))
      listOfBooks.remove(book);


      System.err.println("After deleting : " + listOfBooks);



      I'm using Netbeans 8.2, Windows 7 32bit, with JDK 1.8.0_131
      What's wrong ?







      java exception






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked 4 hours ago









      dobrivoje

      876




      876






















          3 Answers
          3






          active

          oldest

          votes

















          up vote
          5
          down vote













          List.remove() will not throw ConcurrentModificationException when it removes the second last element from the list.



          Quoting from this Java Bug (JDK-4902078) .




          When the Collections Framework was added to the platform it was deemed too expensive to check for comodification once rather than twice per iteration; the check was made on Iterator.next rather than Iterator.hasNext. Expert reviewers thought this was sufficient. They were unaware that it fails to detect one important case: if an element is removed from the list immediately prior to the final call to hasNext in an iteration, the call returns false and the iteration terminates, silently ignoring the last element on the list.




          You can also check this answer :-



          https://stackoverflow.com/a/8189786/1992276






          share|improve this answer




















          • What i concluded is that this bug Java Bug (JDK-4902078) still persists. I simply added more "add()" lines, and CM exception occurs only on elements not equals to before-last-element. If I correctly understood this bug status, this is closed and won't fixed task ? This means that decision is made that this bug will stay present, right ?
            – dobrivoje
            1 hour ago


















          up vote
          3
          down vote













          There are two ways used to iterate over an collection: enumeration and iterator.



          First one allows for the collection to be modified during iteration (fail slow), second does not (fail fast). In a for-each loop you are using an iterator, so any modification to the collection, during it's iteration would cause an exception.



          You have 3 choices, to solve this problem:



          Use an iterator instead:



          Iterator<String> bookIt = listOfBooks.iterator();
          while(bookIt.hasNext())
          String book = bookIt.next();
          if (book.contains("Java"))
          bookIt.remove();




          Create a new list with only acceptable elements (filter out the unwanted):



           List<String> booksWithNoCode = listOfBooks.stream()
          .filter(book-> !book.contains("Code"))
          .collect(toList())


          Use Collection.removeIf(), you will remove all elements from the list, that are matching given criteria.



          listOfBooks.removeIf(book-> book.contains("Code"))


          You can find more information in this post and here.






          share|improve this answer


















          • 2




            I agree on your proposals, I'm aware that the Iterator solution is the most correct one along with a stream solution (which works as it is unmodifiable) ,but that's not my question. I expect in both situations CM exception, and I get it only in case of "Code", not in case of "Java"
            – dobrivoje
            4 hours ago











          • What do you mean by "enumerator"? That isn't a term used in Java.
            – chrylis
            3 hours ago










          • Sorry, I have fixed that.
            – Beri
            2 hours ago

















          up vote
          2
          down vote













          You can't modify the listOfBooks while you are iterating though it with the for each loop.




          edit:



          for (String book : listOfBooks) 
          if (book.contains("Code"))
          listOfBooks.remove(book);




          Is the same as:



           for (Iterator<String> i = listOfBooks.iterator(); i.hasNext();) 
          String book = i.next();
          if (book.contains("Code"))
          listOfBooks.remove(book);




          http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/tip/src/share/classes/java/util/ArrayList.java



          The key in the arraylist code is:



          public boolean remove(Object o) 
          if (o == null)
          for (int index = 0; index < size; index++)
          if (elementData[index] == null)
          fastRemove(index);
          return true;

          else
          for (int index = 0; index < size; index++)
          if (o.equals(elementData[index]))
          fastRemove(index);
          return true;


          return false;


          /*
          * Private remove method that skips bounds checking and does not
          * return the value removed.
          */
          private void fastRemove(int index)
          modCount++;
          int numMoved = size - index - 1;
          if (numMoved > 0)
          System.arraycopy(elementData, index+1, elementData, index,
          numMoved);
          elementData[--size] = null; // clear to let GC do its work



          and the iterator code:



           public boolean hasNext() 
          return cursor != size;


          @SuppressWarnings("unchecked")
          public E next()
          checkForComodification();
          int i = cursor;
          if (i >= size)
          throw new NoSuchElementException();
          Object elementData = ArrayList.this.elementData;
          if (i >= elementData.length)
          throw new ConcurrentModificationException();
          cursor = i + 1;
          return (E) elementData[lastRet = i];



          The cursor always points to the next element so when you get the "Effective Java" i = 2 but cursor is 3.



          When you call the remove the cursor is at 3 and the size is 4.



          The size is then decremented by the remove and now cursor == size and the next hasNext() returns false ending the loop.






          share|improve this answer






















          • that's true, however, the only difference are the data theme self, so I expected in both cases to see exception, don't you agree ?
            – dobrivoje
            4 hours ago







          • 2




            hmm thats interesting... It seems you can only remove the second to the last element safely... I will dig into it a bit see if I find something :)
            – Charles
            4 hours ago










          Your Answer





          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "1"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          convertImagesToLinks: true,
          noModals: false,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );













           

          draft saved


          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52689189%2fweird-java-concurrent-modification-exception-example%23new-answer', 'question_page');

          );

          Post as a guest






























          3 Answers
          3






          active

          oldest

          votes








          3 Answers
          3






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          up vote
          5
          down vote













          List.remove() will not throw ConcurrentModificationException when it removes the second last element from the list.



          Quoting from this Java Bug (JDK-4902078) .




          When the Collections Framework was added to the platform it was deemed too expensive to check for comodification once rather than twice per iteration; the check was made on Iterator.next rather than Iterator.hasNext. Expert reviewers thought this was sufficient. They were unaware that it fails to detect one important case: if an element is removed from the list immediately prior to the final call to hasNext in an iteration, the call returns false and the iteration terminates, silently ignoring the last element on the list.




          You can also check this answer :-



          https://stackoverflow.com/a/8189786/1992276






          share|improve this answer




















          • What i concluded is that this bug Java Bug (JDK-4902078) still persists. I simply added more "add()" lines, and CM exception occurs only on elements not equals to before-last-element. If I correctly understood this bug status, this is closed and won't fixed task ? This means that decision is made that this bug will stay present, right ?
            – dobrivoje
            1 hour ago















          up vote
          5
          down vote













          List.remove() will not throw ConcurrentModificationException when it removes the second last element from the list.



          Quoting from this Java Bug (JDK-4902078) .




          When the Collections Framework was added to the platform it was deemed too expensive to check for comodification once rather than twice per iteration; the check was made on Iterator.next rather than Iterator.hasNext. Expert reviewers thought this was sufficient. They were unaware that it fails to detect one important case: if an element is removed from the list immediately prior to the final call to hasNext in an iteration, the call returns false and the iteration terminates, silently ignoring the last element on the list.




          You can also check this answer :-



          https://stackoverflow.com/a/8189786/1992276






          share|improve this answer




















          • What i concluded is that this bug Java Bug (JDK-4902078) still persists. I simply added more "add()" lines, and CM exception occurs only on elements not equals to before-last-element. If I correctly understood this bug status, this is closed and won't fixed task ? This means that decision is made that this bug will stay present, right ?
            – dobrivoje
            1 hour ago













          up vote
          5
          down vote










          up vote
          5
          down vote









          List.remove() will not throw ConcurrentModificationException when it removes the second last element from the list.



          Quoting from this Java Bug (JDK-4902078) .




          When the Collections Framework was added to the platform it was deemed too expensive to check for comodification once rather than twice per iteration; the check was made on Iterator.next rather than Iterator.hasNext. Expert reviewers thought this was sufficient. They were unaware that it fails to detect one important case: if an element is removed from the list immediately prior to the final call to hasNext in an iteration, the call returns false and the iteration terminates, silently ignoring the last element on the list.




          You can also check this answer :-



          https://stackoverflow.com/a/8189786/1992276






          share|improve this answer












          List.remove() will not throw ConcurrentModificationException when it removes the second last element from the list.



          Quoting from this Java Bug (JDK-4902078) .




          When the Collections Framework was added to the platform it was deemed too expensive to check for comodification once rather than twice per iteration; the check was made on Iterator.next rather than Iterator.hasNext. Expert reviewers thought this was sufficient. They were unaware that it fails to detect one important case: if an element is removed from the list immediately prior to the final call to hasNext in an iteration, the call returns false and the iteration terminates, silently ignoring the last element on the list.




          You can also check this answer :-



          https://stackoverflow.com/a/8189786/1992276







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered 3 hours ago









          GanitK

          311315




          311315











          • What i concluded is that this bug Java Bug (JDK-4902078) still persists. I simply added more "add()" lines, and CM exception occurs only on elements not equals to before-last-element. If I correctly understood this bug status, this is closed and won't fixed task ? This means that decision is made that this bug will stay present, right ?
            – dobrivoje
            1 hour ago

















          • What i concluded is that this bug Java Bug (JDK-4902078) still persists. I simply added more "add()" lines, and CM exception occurs only on elements not equals to before-last-element. If I correctly understood this bug status, this is closed and won't fixed task ? This means that decision is made that this bug will stay present, right ?
            – dobrivoje
            1 hour ago
















          What i concluded is that this bug Java Bug (JDK-4902078) still persists. I simply added more "add()" lines, and CM exception occurs only on elements not equals to before-last-element. If I correctly understood this bug status, this is closed and won't fixed task ? This means that decision is made that this bug will stay present, right ?
          – dobrivoje
          1 hour ago





          What i concluded is that this bug Java Bug (JDK-4902078) still persists. I simply added more "add()" lines, and CM exception occurs only on elements not equals to before-last-element. If I correctly understood this bug status, this is closed and won't fixed task ? This means that decision is made that this bug will stay present, right ?
          – dobrivoje
          1 hour ago













          up vote
          3
          down vote













          There are two ways used to iterate over an collection: enumeration and iterator.



          First one allows for the collection to be modified during iteration (fail slow), second does not (fail fast). In a for-each loop you are using an iterator, so any modification to the collection, during it's iteration would cause an exception.



          You have 3 choices, to solve this problem:



          Use an iterator instead:



          Iterator<String> bookIt = listOfBooks.iterator();
          while(bookIt.hasNext())
          String book = bookIt.next();
          if (book.contains("Java"))
          bookIt.remove();




          Create a new list with only acceptable elements (filter out the unwanted):



           List<String> booksWithNoCode = listOfBooks.stream()
          .filter(book-> !book.contains("Code"))
          .collect(toList())


          Use Collection.removeIf(), you will remove all elements from the list, that are matching given criteria.



          listOfBooks.removeIf(book-> book.contains("Code"))


          You can find more information in this post and here.






          share|improve this answer


















          • 2




            I agree on your proposals, I'm aware that the Iterator solution is the most correct one along with a stream solution (which works as it is unmodifiable) ,but that's not my question. I expect in both situations CM exception, and I get it only in case of "Code", not in case of "Java"
            – dobrivoje
            4 hours ago











          • What do you mean by "enumerator"? That isn't a term used in Java.
            – chrylis
            3 hours ago










          • Sorry, I have fixed that.
            – Beri
            2 hours ago














          up vote
          3
          down vote













          There are two ways used to iterate over an collection: enumeration and iterator.



          First one allows for the collection to be modified during iteration (fail slow), second does not (fail fast). In a for-each loop you are using an iterator, so any modification to the collection, during it's iteration would cause an exception.



          You have 3 choices, to solve this problem:



          Use an iterator instead:



          Iterator<String> bookIt = listOfBooks.iterator();
          while(bookIt.hasNext())
          String book = bookIt.next();
          if (book.contains("Java"))
          bookIt.remove();




          Create a new list with only acceptable elements (filter out the unwanted):



           List<String> booksWithNoCode = listOfBooks.stream()
          .filter(book-> !book.contains("Code"))
          .collect(toList())


          Use Collection.removeIf(), you will remove all elements from the list, that are matching given criteria.



          listOfBooks.removeIf(book-> book.contains("Code"))


          You can find more information in this post and here.






          share|improve this answer


















          • 2




            I agree on your proposals, I'm aware that the Iterator solution is the most correct one along with a stream solution (which works as it is unmodifiable) ,but that's not my question. I expect in both situations CM exception, and I get it only in case of "Code", not in case of "Java"
            – dobrivoje
            4 hours ago











          • What do you mean by "enumerator"? That isn't a term used in Java.
            – chrylis
            3 hours ago










          • Sorry, I have fixed that.
            – Beri
            2 hours ago












          up vote
          3
          down vote










          up vote
          3
          down vote









          There are two ways used to iterate over an collection: enumeration and iterator.



          First one allows for the collection to be modified during iteration (fail slow), second does not (fail fast). In a for-each loop you are using an iterator, so any modification to the collection, during it's iteration would cause an exception.



          You have 3 choices, to solve this problem:



          Use an iterator instead:



          Iterator<String> bookIt = listOfBooks.iterator();
          while(bookIt.hasNext())
          String book = bookIt.next();
          if (book.contains("Java"))
          bookIt.remove();




          Create a new list with only acceptable elements (filter out the unwanted):



           List<String> booksWithNoCode = listOfBooks.stream()
          .filter(book-> !book.contains("Code"))
          .collect(toList())


          Use Collection.removeIf(), you will remove all elements from the list, that are matching given criteria.



          listOfBooks.removeIf(book-> book.contains("Code"))


          You can find more information in this post and here.






          share|improve this answer














          There are two ways used to iterate over an collection: enumeration and iterator.



          First one allows for the collection to be modified during iteration (fail slow), second does not (fail fast). In a for-each loop you are using an iterator, so any modification to the collection, during it's iteration would cause an exception.



          You have 3 choices, to solve this problem:



          Use an iterator instead:



          Iterator<String> bookIt = listOfBooks.iterator();
          while(bookIt.hasNext())
          String book = bookIt.next();
          if (book.contains("Java"))
          bookIt.remove();




          Create a new list with only acceptable elements (filter out the unwanted):



           List<String> booksWithNoCode = listOfBooks.stream()
          .filter(book-> !book.contains("Code"))
          .collect(toList())


          Use Collection.removeIf(), you will remove all elements from the list, that are matching given criteria.



          listOfBooks.removeIf(book-> book.contains("Code"))


          You can find more information in this post and here.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited 3 hours ago

























          answered 4 hours ago









          Beri

          7,82531638




          7,82531638







          • 2




            I agree on your proposals, I'm aware that the Iterator solution is the most correct one along with a stream solution (which works as it is unmodifiable) ,but that's not my question. I expect in both situations CM exception, and I get it only in case of "Code", not in case of "Java"
            – dobrivoje
            4 hours ago











          • What do you mean by "enumerator"? That isn't a term used in Java.
            – chrylis
            3 hours ago










          • Sorry, I have fixed that.
            – Beri
            2 hours ago












          • 2




            I agree on your proposals, I'm aware that the Iterator solution is the most correct one along with a stream solution (which works as it is unmodifiable) ,but that's not my question. I expect in both situations CM exception, and I get it only in case of "Code", not in case of "Java"
            – dobrivoje
            4 hours ago











          • What do you mean by "enumerator"? That isn't a term used in Java.
            – chrylis
            3 hours ago










          • Sorry, I have fixed that.
            – Beri
            2 hours ago







          2




          2




          I agree on your proposals, I'm aware that the Iterator solution is the most correct one along with a stream solution (which works as it is unmodifiable) ,but that's not my question. I expect in both situations CM exception, and I get it only in case of "Code", not in case of "Java"
          – dobrivoje
          4 hours ago





          I agree on your proposals, I'm aware that the Iterator solution is the most correct one along with a stream solution (which works as it is unmodifiable) ,but that's not my question. I expect in both situations CM exception, and I get it only in case of "Code", not in case of "Java"
          – dobrivoje
          4 hours ago













          What do you mean by "enumerator"? That isn't a term used in Java.
          – chrylis
          3 hours ago




          What do you mean by "enumerator"? That isn't a term used in Java.
          – chrylis
          3 hours ago












          Sorry, I have fixed that.
          – Beri
          2 hours ago




          Sorry, I have fixed that.
          – Beri
          2 hours ago










          up vote
          2
          down vote













          You can't modify the listOfBooks while you are iterating though it with the for each loop.




          edit:



          for (String book : listOfBooks) 
          if (book.contains("Code"))
          listOfBooks.remove(book);




          Is the same as:



           for (Iterator<String> i = listOfBooks.iterator(); i.hasNext();) 
          String book = i.next();
          if (book.contains("Code"))
          listOfBooks.remove(book);




          http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/tip/src/share/classes/java/util/ArrayList.java



          The key in the arraylist code is:



          public boolean remove(Object o) 
          if (o == null)
          for (int index = 0; index < size; index++)
          if (elementData[index] == null)
          fastRemove(index);
          return true;

          else
          for (int index = 0; index < size; index++)
          if (o.equals(elementData[index]))
          fastRemove(index);
          return true;


          return false;


          /*
          * Private remove method that skips bounds checking and does not
          * return the value removed.
          */
          private void fastRemove(int index)
          modCount++;
          int numMoved = size - index - 1;
          if (numMoved > 0)
          System.arraycopy(elementData, index+1, elementData, index,
          numMoved);
          elementData[--size] = null; // clear to let GC do its work



          and the iterator code:



           public boolean hasNext() 
          return cursor != size;


          @SuppressWarnings("unchecked")
          public E next()
          checkForComodification();
          int i = cursor;
          if (i >= size)
          throw new NoSuchElementException();
          Object elementData = ArrayList.this.elementData;
          if (i >= elementData.length)
          throw new ConcurrentModificationException();
          cursor = i + 1;
          return (E) elementData[lastRet = i];



          The cursor always points to the next element so when you get the "Effective Java" i = 2 but cursor is 3.



          When you call the remove the cursor is at 3 and the size is 4.



          The size is then decremented by the remove and now cursor == size and the next hasNext() returns false ending the loop.






          share|improve this answer






















          • that's true, however, the only difference are the data theme self, so I expected in both cases to see exception, don't you agree ?
            – dobrivoje
            4 hours ago







          • 2




            hmm thats interesting... It seems you can only remove the second to the last element safely... I will dig into it a bit see if I find something :)
            – Charles
            4 hours ago














          up vote
          2
          down vote













          You can't modify the listOfBooks while you are iterating though it with the for each loop.




          edit:



          for (String book : listOfBooks) 
          if (book.contains("Code"))
          listOfBooks.remove(book);




          Is the same as:



           for (Iterator<String> i = listOfBooks.iterator(); i.hasNext();) 
          String book = i.next();
          if (book.contains("Code"))
          listOfBooks.remove(book);




          http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/tip/src/share/classes/java/util/ArrayList.java



          The key in the arraylist code is:



          public boolean remove(Object o) 
          if (o == null)
          for (int index = 0; index < size; index++)
          if (elementData[index] == null)
          fastRemove(index);
          return true;

          else
          for (int index = 0; index < size; index++)
          if (o.equals(elementData[index]))
          fastRemove(index);
          return true;


          return false;


          /*
          * Private remove method that skips bounds checking and does not
          * return the value removed.
          */
          private void fastRemove(int index)
          modCount++;
          int numMoved = size - index - 1;
          if (numMoved > 0)
          System.arraycopy(elementData, index+1, elementData, index,
          numMoved);
          elementData[--size] = null; // clear to let GC do its work



          and the iterator code:



           public boolean hasNext() 
          return cursor != size;


          @SuppressWarnings("unchecked")
          public E next()
          checkForComodification();
          int i = cursor;
          if (i >= size)
          throw new NoSuchElementException();
          Object elementData = ArrayList.this.elementData;
          if (i >= elementData.length)
          throw new ConcurrentModificationException();
          cursor = i + 1;
          return (E) elementData[lastRet = i];



          The cursor always points to the next element so when you get the "Effective Java" i = 2 but cursor is 3.



          When you call the remove the cursor is at 3 and the size is 4.



          The size is then decremented by the remove and now cursor == size and the next hasNext() returns false ending the loop.






          share|improve this answer






















          • that's true, however, the only difference are the data theme self, so I expected in both cases to see exception, don't you agree ?
            – dobrivoje
            4 hours ago







          • 2




            hmm thats interesting... It seems you can only remove the second to the last element safely... I will dig into it a bit see if I find something :)
            – Charles
            4 hours ago












          up vote
          2
          down vote










          up vote
          2
          down vote









          You can't modify the listOfBooks while you are iterating though it with the for each loop.




          edit:



          for (String book : listOfBooks) 
          if (book.contains("Code"))
          listOfBooks.remove(book);




          Is the same as:



           for (Iterator<String> i = listOfBooks.iterator(); i.hasNext();) 
          String book = i.next();
          if (book.contains("Code"))
          listOfBooks.remove(book);




          http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/tip/src/share/classes/java/util/ArrayList.java



          The key in the arraylist code is:



          public boolean remove(Object o) 
          if (o == null)
          for (int index = 0; index < size; index++)
          if (elementData[index] == null)
          fastRemove(index);
          return true;

          else
          for (int index = 0; index < size; index++)
          if (o.equals(elementData[index]))
          fastRemove(index);
          return true;


          return false;


          /*
          * Private remove method that skips bounds checking and does not
          * return the value removed.
          */
          private void fastRemove(int index)
          modCount++;
          int numMoved = size - index - 1;
          if (numMoved > 0)
          System.arraycopy(elementData, index+1, elementData, index,
          numMoved);
          elementData[--size] = null; // clear to let GC do its work



          and the iterator code:



           public boolean hasNext() 
          return cursor != size;


          @SuppressWarnings("unchecked")
          public E next()
          checkForComodification();
          int i = cursor;
          if (i >= size)
          throw new NoSuchElementException();
          Object elementData = ArrayList.this.elementData;
          if (i >= elementData.length)
          throw new ConcurrentModificationException();
          cursor = i + 1;
          return (E) elementData[lastRet = i];



          The cursor always points to the next element so when you get the "Effective Java" i = 2 but cursor is 3.



          When you call the remove the cursor is at 3 and the size is 4.



          The size is then decremented by the remove and now cursor == size and the next hasNext() returns false ending the loop.






          share|improve this answer














          You can't modify the listOfBooks while you are iterating though it with the for each loop.




          edit:



          for (String book : listOfBooks) 
          if (book.contains("Code"))
          listOfBooks.remove(book);




          Is the same as:



           for (Iterator<String> i = listOfBooks.iterator(); i.hasNext();) 
          String book = i.next();
          if (book.contains("Code"))
          listOfBooks.remove(book);




          http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/tip/src/share/classes/java/util/ArrayList.java



          The key in the arraylist code is:



          public boolean remove(Object o) 
          if (o == null)
          for (int index = 0; index < size; index++)
          if (elementData[index] == null)
          fastRemove(index);
          return true;

          else
          for (int index = 0; index < size; index++)
          if (o.equals(elementData[index]))
          fastRemove(index);
          return true;


          return false;


          /*
          * Private remove method that skips bounds checking and does not
          * return the value removed.
          */
          private void fastRemove(int index)
          modCount++;
          int numMoved = size - index - 1;
          if (numMoved > 0)
          System.arraycopy(elementData, index+1, elementData, index,
          numMoved);
          elementData[--size] = null; // clear to let GC do its work



          and the iterator code:



           public boolean hasNext() 
          return cursor != size;


          @SuppressWarnings("unchecked")
          public E next()
          checkForComodification();
          int i = cursor;
          if (i >= size)
          throw new NoSuchElementException();
          Object elementData = ArrayList.this.elementData;
          if (i >= elementData.length)
          throw new ConcurrentModificationException();
          cursor = i + 1;
          return (E) elementData[lastRet = i];



          The cursor always points to the next element so when you get the "Effective Java" i = 2 but cursor is 3.



          When you call the remove the cursor is at 3 and the size is 4.



          The size is then decremented by the remove and now cursor == size and the next hasNext() returns false ending the loop.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited 3 hours ago

























          answered 4 hours ago









          Charles

          32916




          32916











          • that's true, however, the only difference are the data theme self, so I expected in both cases to see exception, don't you agree ?
            – dobrivoje
            4 hours ago







          • 2




            hmm thats interesting... It seems you can only remove the second to the last element safely... I will dig into it a bit see if I find something :)
            – Charles
            4 hours ago
















          • that's true, however, the only difference are the data theme self, so I expected in both cases to see exception, don't you agree ?
            – dobrivoje
            4 hours ago







          • 2




            hmm thats interesting... It seems you can only remove the second to the last element safely... I will dig into it a bit see if I find something :)
            – Charles
            4 hours ago















          that's true, however, the only difference are the data theme self, so I expected in both cases to see exception, don't you agree ?
          – dobrivoje
          4 hours ago





          that's true, however, the only difference are the data theme self, so I expected in both cases to see exception, don't you agree ?
          – dobrivoje
          4 hours ago





          2




          2




          hmm thats interesting... It seems you can only remove the second to the last element safely... I will dig into it a bit see if I find something :)
          – Charles
          4 hours ago




          hmm thats interesting... It seems you can only remove the second to the last element safely... I will dig into it a bit see if I find something :)
          – Charles
          4 hours ago

















           

          draft saved


          draft discarded















































           


          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52689189%2fweird-java-concurrent-modification-exception-example%23new-answer', 'question_page');

          );

          Post as a guest













































































          Comments

          Popular posts from this blog

          What does second last employer means? [closed]

          Installing NextGIS Connect into QGIS 3?

          One-line joke