ArrayList is a very common class in Java development, and often comes across situations where you need to ArrayList to delete elements. At this point, no one uses the Foreach loop to traverse the list because it throws java.util.ConcurrentModificationException exceptions. For example, the following code throws the exception: List list = new ArrayList (); List.add ("1"); List.add ("2"); List.add ("3"); List.add ("4"); List.add ("5"); for (String item:list) {if (Item.equals ("3")) {System.out.println (item); List.remove (item)}} System.out.println (List.size ()); 1 2 3 4 5 6 7 8 9 list = new ArrayList (); list. Add ("1"); list. Add ("2"); list. Add ("3"); list. Add ("4"); list. Add ("5"); for (String item:list) { if (itEm. Equals ("3")) { System. Out. println (item); list. Remove (item); } } System. Out. println (list. Size ());
That is not deleting an element when the Foreach loop is bound to throw the exception. The answer is in the negative.
See this code: List List = new ArrayList (); List.add ("1"); List.add ("2"); List.add ("3"); List.add ("4"); List.add ("5"); for (String item:list) {if (Item.equals ("4")) {System.out.println (item); List.remove (item)}} System.out.println (List.size ()); 1 2 3 4 5 6 7 8 9 list = new ArrayList (); list. Add ("1"); list. Add ("2"); list. Add ("3"); list. Add ("4"); list. Add ("5"); for (String item:list) { if (item. Equals ("4")) {   ; System. Out. PRINTLN (item); list. Remove (item); } } System. Out. println (list. Size ());
This code and the code above simply change the index of the element to be deleted to 4, and the code does not throw an exception. Why, then?
Then do a few experiments on this code, the element to delete the index number from 1 to 5 in turn, and found that, in addition to delete 4, delete other elements will throw an exception. Then add the list to the number of elements to 7 try, this time you can see that the rule is that only delete the penultimate element when the exception will not throw, delete other elements will throw an exception.
Well, the rules know, you can from the point of view of the code to uncover the answer.
First of all, the Java foreach Loop is based on the list object to create a iterator iteration object, using this iterative object to traverse the list, which is equivalent to the list object in the traversal of the elements of the iterator, if you want to delete the list to operate, Must go through the iterator, otherwise iterator traversal will be chaotic, so directly to the list to delete, iterator will throw concurrentmodificationexception exception
In fact, each foreach iteration has two operations: Iterator.hasnext ()//Determine if there is a next element item = Iterator.next ()//What the next element is, and assign it to the item variable in the example above
The code for the Hasnext () method is as follows: Public E next () {checkforcomodification (), try {e next = get (cursor), Lastret = cursor++; return next; catch (Indexoutofboundsexception e) {checkforcomodification (); throw new Nosuchelementexception ();}} final void Checkforcomodification () {if (Modcount!= expectedmodcount) throw new Concurrentmodificationexception ();} 1 2 3 4 5 6 7 8 9 of the public E next () { checkforcom Odification (); try { E next = get (cursor); Lastret = cursor ++ ; return next; } catch (Indexoutofboundsexception e) { checkForComodification (); throw New Nosuchelementexception (); } final void Checkforcomodification () { & nbsp; if (modcount!= expectedmodcount) throw new Concurrentmodificationexception (); }}
At this point you will find that this exception is thrown in the checkforcomodification of the next method, which is thrown because Modcount!= expectedmodcount modcount refers to the list object from new to the current number of changes , when you call the Add or Remove method of the list, this modcount will automatically increase or decrease; Expectedmodcount refers to how many times the iterator now expects the list to be modified.
When iterator is created, the Modcount is assigned to the Expectedmodcount, but the add and remove methods of the list are not automatically added or subtracted at the same time Expectedmodcount, which results in two count not equal. Thus throwing an exception.
If you want to keep it from throwing an exception, one way is to let iterator return false when calling the Hasnext () method so that it does not go into the next () method. Here cursor refers to the index number of an element that is currently traversed. For example, when you delete the penultimate element, cursor points to the last element, and when you delete the penultimate element, the cursor and size () are exactly equal, so Hasnext () returns false, and the traversal ends so that the penultimate element is successfully deleted.
Superstition, the Foreach Loop traversal can not delete the element is not absolute, the penultimate element is safe to delete ~ ~ (of course, the above ideas are based on the list is not shared by multithreading)