In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-20 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article introduces the relevant knowledge of "Why the deletion operation is not required in foreach in Java". In the operation of actual cases, many people will encounter such a dilemma, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!
For the town building, first use an English passage to explain fail-fast.
In systems design, a fail-fast system is one which immediately reports at its interface any condition that is likely to indicate a failure. Fail-fast systems are usually designed to stop normal operation rather than attempt to continue a possibly flawed process. Such designs often check the system's state at several points in an operation, so any failures can be detected early. The responsibility of a fail-fast module is detecting errors, then letting the next-highest level of the system handle them.
The general meaning of this passage is that fail-fast is a general system design idea that as soon as an error is detected, an exception is thrown and the program will no longer be executed.
Public void test (Wanger wanger) {if (wanger = = null) {throw new RuntimeException ("wanger cannot be empty");} System.out.println (wanger.toString ());}
As soon as wanger is detected as null, an exception is thrown, leaving it up to the caller to decide what to do in this case, and wanger.toString () is not executed next-- avoiding more serious errors.
Most of the time, we will classify fail-fast as an error detection mechanism of the Java collection framework, but in fact, fail-fast is not unique to the Java collection framework.
The reason we put fail-fast in the collection framework section is that the problem is easier to reproduce.
List list = new ArrayList (); list.add (Silent King II); list.add (Silent King III); list.add ("A really interesting programmer"); for (String str: list) {if (Silent King II) .equals (str) {list.remove (str);}} System.out.println (list)
There seems to be nothing wrong with this code, but it reports an error when it runs.
Based on the wrong stack information, we can navigate to line 901 of ArrayList.
Final void checkForComodification () {if (modCount! = expectedModCount) throw new ConcurrentModificationException ();}
That is, the remove triggers the execution of the checkForComodification method, which compares modCount with expectedModCount and throws a ConcurrentModificationException exception when it finds that the two are different.
Why do you execute the checkForComodification method?
Because for-each is essentially a syntactic sugar, the bottom layer is achieved through the iterator Iterator with the while loop. Take a look at the decompiled bytecode.
List list = new ArrayList (); list.add (Silent King II); list.add (Silent King III); list.add ("A really interesting programmer"); Iterator var2 = list.iterator (); while (var2.hasNext ()) {String str = (String) var2.next (); if (Silent King II .equals (str)) {list.remove (str);} System.out.println (list)
Take a look at ArrayList's iterator method:
Public Iterator iterator () {return new Itr ();}
The inner class Itr implements the Iterator interface.
Private class Itr implements Iterator {int cursor; / / index of next element to return int lastRet =-1; / / index of last element returned;-1 if no such int expectedModCount = modCount; Itr () {} public boolean hasNext () {return cursor! = size;} @ SuppressWarnings ("unchecked") public E next () {checkForComodification (); int I = cursor; Object [] elementData = ArrayList.this.elementData If (I > = elementData.length) throw new ConcurrentModificationException (); cursor = I + 1; return (E) elementData [lastRet = I];}}
That is, when new Itr (), expectedModCount is assigned to modCount, and modCount is a member variable of List, indicating the number of times the collection has been modified. Because list has executed the add method three times before.
The add method calls the ensureCapacityInternal method
The ensureCapacityInternal method calls the ensureExplicitCapacity method
ModCount++ is executed in the ensureExplicitCapacity method
So the value of modCount is 3 after three times of add, so the value of expectedModCount after new Itr () is also 3.
When the first loop is executed, it is found that Silence II equals str, so list.remove (str) is executed.
The remove method calls the fastRemove method
ModCount++ is executed in the fastRemove method
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}
The value of modCount becomes 4.
When the second loop is executed, the next method of Itr (String str = (String) var3.next ();) is executed, and the next method calls the checkForComodification method. In this case, the expectedModCount is 3 and mod _ count is 4, so you have to throw a ConcurrentModificationException exception.
In fact, it is also mentioned in Alibaba's Java development manual that you should not perform remove/add operations on elements in the for-each loop. Please use Iterator method for remove element.
The reason is actually what we have analyzed above, because of the fail-fast protection mechanism.
So how do you delete elements correctly? 1) breakList list = new ArrayList () after remove; list.add (Silent King II); list.add (Silent King III); list.add ("A really interesting programmer"); for (String str: list) {if (Silent King II .equals (str)) {list.remove (str); break;}}
The break post-loop is no longer traversed, which means that the next method of Iterator is no longer executed, which means that the checkForComodification method is no longer executed, so the exception is not thrown.
However, when there are duplicate elements in the List to delete, the break is not appropriate.
2) for cycle List list = new ArrayList (); list.add (Silent King 2); list.add (Silent King 3); list.add ("A really interesting programmer"); for (int I = 0, n = list.size (); I < n; iSilence +) {String str = list.get (I); if (Silent King II. Equals (str)) {list.remove (str) }}
Although the for loop can avoid the fail-fast protection mechanism, that is, it no longer throws an exception after the remove element; however, this program is problematic in principle. Why?
In the first loop, I is 0reList.size () is 3, but when the remove method is executed, I = 1MagneList.size () becomes 2, because the size of list has changed after remove, which means that the element of "Silent King 3" has been skipped. Do you understand?
Before remove, list.get (1) was the "Silent King 3"; but after remove, list.get (1) became "a really interesting programmer", while list.get (0) became the "Silent King 3".
3) use IteratorList list = new ArrayList (); list.add (Silent King II); list.add (Silent King III); list.add ("A really interesting programmer"); Iterator itr = list.iterator (); while (itr.hasNext ()) {String str = itr.next (); if (Silent King II .equals (str)) {itr.remove ();}}
Why can you avoid the fail-fast protection mechanism by using Iterator's remove method? Just take a look at the source code of remove.
Public void remove () {if (lastRet < 0) throw new IllegalStateException (); checkForComodification (); try {ArrayList.this.remove (lastRet); cursor = lastRet; lastRet =-1; expectedModCount = modCount;} catch (IndexOutOfBoundsException ex) {throw new ConcurrentModificationException ();}}
ExpectedModCount = modCount is executed after deletion, which ensures the synchronization of expectedModCount and modCount.
This is the end of the content of "Why the deletion operation is not required in the foreach in Java". Thank you for your reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.