1. Rookie mistakes

public static void main(String[] args) { List<String> platformList = new ArrayList<>(); Platformlist.add (" blog garden "); platformList.add("CSDN"); PlatformList. Add (" nuggets "); For (String platform: platformList) {if (platform.equals(" blog ")) {platformList.remove(platform); } } System.out.println(platformList); }Copy the code

Then with confidence to run, the result was thrown exception of Java. Util. ConcurrentModificationException and translated into Chinese is: concurrent modification abnormalities.

Are you confused, wondering why?

Let’s first look at the bytecode generated by the above code, as follows:

As you can see, the foreach loop actually executes using Iterator, using hasNext () and next() as its core methods.

Now, how is the ArrayList class Iterator implemented?

As can be seen, when the next() method is called to get the next element, the first line of code is called checkForComodification(). The core logic of the method is to compare the values of the two variables, modCount and expectedModCount.

In the example above, the modCount and expectedModCount are both 3 at the beginning, so it is ok to get the “bloggarden” element the first time, but when you finish executing the following line:

platformList.remove(platform);
Copy the code

ModCount is changed to 4.

So on the second element, modCount and expectedModCount value is not equal, so throw out the Java. Util. ConcurrentModificationException anomalies.

Since we can’t use foreach to do this, how do we do it?

There are three main methods:

  1. Use Iterator’s remove() method
  2. Use the for loop to traverse in positive order
  3. Use the for loop to iterate backwards

Let’s go through them.

2. Use the remove() method of Iterator

Iterator’s remove() method is implemented as follows:

public static void main(String[] args) { List<String> platformList = new ArrayList<>(); Platformlist.add (" blog garden "); platformList.add("CSDN"); PlatformList. Add (" nuggets "); Iterator<String> iterator = platformList.iterator(); while (iterator.hasNext()) { String platform = iterator.next(); Iterator.remove (); if (platform.equals(" blog ")) {iterator.remove(); } } System.out.println(platformList); }Copy the code

The output is:

[CSDN, Denver]Copy the code

Iterator.remove (); Is that ok?

Let’s take a look at the source code:

You can see, every time delete an element, modCount value will be assigned to again expectedModCount, so two variables are equal, not trigger Java. Util. ConcurrentModificationException anomalies.

3. Use the for loop to traverse in positive order

Positive traversal with the for loop is implemented as follows:

public static void main(String[] args) { List<String> platformList = new ArrayList<>(); Platformlist.add (" blog garden "); platformList.add("CSDN"); PlatformList. Add (" nuggets "); for (int i = 0; i < platformList.size(); i++) { String item = platformList.get(i); Platformlist. remove(I); if (item.equals(" blog-park ")) {platformList.remove(I); i = i - 1; } } System.out.println(platformList); }Copy the code

Delete an element from an array using the subscript of the array. The value of the subscript must be corrected after the element is deleted:

i = i - 1;
Copy the code

Why would I fix the value of the subscript?

Because at the beginning the index of the element looks like this:

After the first loop removes the element “blogosphere”, the subscript of the element becomes the following:

In the second loop, the value of “I” is 1, which means that the element “CSDN” is skipped, so after deleting the element, we need to correct the subscript, which is also the code above I = i-1; The purpose of.

4. Use the for loop to iterate backwards

Reverse traversal with the for loop is implemented as follows:

public static void main(String[] args) { List<String> platformList = new ArrayList<>(); Platformlist.add (" blog garden "); platformList.add("CSDN"); PlatformList. Add (" nuggets "); for (int i = platformList.size() - 1; i >= 0; i--) { String item = platformList.get(i); If (item.equals(" equals ")) {platformList.remove(I); } } System.out.println(platformList); }Copy the code

This is done in the same way as if we were traversing through the for loop, except that we don’t have to fix the subscript, because we started with the element’s subscript:

After the first loop removes the element “nuggets”, the subscript of the element becomes the following:

In the second loop, I is 1, which means that the element CSDN is reached, which does not cause the element to be skipped, so there is no need to modify the subscript.

5. Use the removeIf() method (recommended)

As of JDK1.8, we can use removeIf() instead of remove() as an Iterator.

So the original code:

Iterator<String> iterator = platformList.iterator(); while (iterator.hasNext()) { String platform = iterator.next(); Iterator.remove (); if (platform.equals(" blog ")) {iterator.remove(); }}Copy the code

This can be simplified to 1 line of code like this, very succinctly:

Platformlist.removeif (platform -> ".equals(platform) ");Copy the code

Iterator removeIf() : Iterator removeIf() : Iterator removeIf() : Iterator removeIf() : Iterator removeIf() : Iterator removeIf() : Iterator removeIf() : Iterator removeIf()

6. Do I need to correct the subscript when I use the for loop to traverse in positive order?

The conclusion: yes.

However, the previous example is not very good, so many readers think that it is ok not to modify the subscript, in fact, it is not, let’s change the example to understand:

List<String> platformList = new ArrayList<>(); Platformlist.add (" blog garden "); Platformlist.add (" blog garden "); platformList.add("CSDN"); PlatformList. Add (" nuggets "); for (int i = 0; i < platformList.size(); i++) { String item = platformList.get(i); If (" equals ".equals(item)) {platformList.remove(I); } } System.out.println(platformList);Copy the code

Output result:

[Blog Park, CSDN, Nuggets]

If you do not fix the subscript, the second element “blog garden” will be skipped in the loop and cannot be deleted, so make sure you fix the subscript:

Reference 7.

How to delete Java collections while iterating through them

Why can’t Java delete elements while iterating