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:
- Use Iterator’s remove() method
- Use the for loop to traverse in positive order
- 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