"Java" list passes the correct way to delete elements

Source: Internet
Author: User
Tags first string concurrentmodificationexception

When you want to delete an element inside a ArrayList, it is easy to make a bug without noticing it. Today, let's talk about the problem of iterating through and deleting elements in the ArrayList loop. First, take a look at the following example:

Importjava.util.ArrayList; Public classArraylistremove { Public Static voidMain (string[] args) {ArrayList<String> list =NewArraylist<string>(); List.add (A); List.add ("B"); List.add ("B"); List.add (C); List.add (C);         Remove (list);  for(String s:list) {System.out.println ("Element:" +s); }    }     Public Static voidRemove (arraylist<string>list) {    }}

Common error notation:

One:

 Public Static void Remove (arraylist<string> list)     {        for (int i = 0; i < List.size (); i++)         {            = list.get (i);             if (S.equals ("B"))             {                List.remove (s);}}    }

Result: The second "B" string was not deleted.

Two:

 Public Static void Remove (arraylist<string> list)     {        for  (String s:list)        {             If (s.equals ("B"))             {                list.remove (s);     }}}

Result: This For-each notation will report concurrent modification exceptions: Java.util.ConcurrentModificationException.

Reason for error: First look at the Remove method in ArrayList, and see how the Remove method with the Parameter object is implemented:

 Public BooleanRemove (Object o) {if(O = =NULL) {             for(intindex = 0; index < size; index++)                if(Elementdata[index] = =NULL) {fastremove (index); return true; }        } Else {             for(intindex = 0; index < size; index++)                if(O.equals (Elementdata[index])) {fastremove (index); return true; }        }        return false; }

The execution path will eventually call the Faseremove method under the Else path:

Private void fastremove (int  index) {        Modcount++        ; int nummoved = size-index-1;         if (nummoved > 0)            System.arraycopy (elementdata, index+1, Elementdata, index,nummoved);        elementdata[null/ let GCdo it work    }

You can see that the System.arraycopy method is executed, which involves the movement of the array elements when the element is deleted. For error notation One, when traversing the first string B because the delete condition is met, the element is removed from the array, and the latter element is moved (that is, the second string b) to the current position, resulting in the next loop over the duration of a string B is not traversed, so it cannot be deleted. In order to avoid this situation, you can reverse the removal of:

 Public Static void Remove (arraylist<string> list)     {        for (int i = list.size ()-1; I >= 0; i--)         {            = list.get (i);             if (S.equals ("B"))             {                List.remove (s);}}    }

The sequential element traversal is not affected because the array is reversed even if an element deletion occurs.

The cause of the error for instance two. The reason is that the foreach notation is the actual iterable, Hasnext, next method shorthand, the problem is also in the Fastremove method above, you can see the first line of the Modcount variable value plus one, But the iterator returned in ArrayList:

 Public Iterator<e> Iterator () {    returnnew  Itr ();}

This returns an iterator inside the Abstractlist class that implements the private class Itr implements Iterator, looking at the next method of this class:

 Public E Next () {        checkforcomodification ();         Try {            = get (cursor);             = cursor++;             return Next;         Catch (indexoutofboundsexception e) {            checkforcomodification ();             Throw New nosuchelementexception ();        }    }

The first line Checkforcomodification method:

Final void checkforcomodification () {    if (modcount! = expectedmodcount        )throw  New  concurrentmodificationexception ();}

This will do an internal change check of the iterator, because the Remove (Object) method above modifies the value of the modcount so that the concurrency modification exception is reported. To avoid this, do not use the ArrayList remove when using iterator iterations (shown or For-each implicit) instead of using the iterator remove.

 Public Static void Remove (arraylist<string> list)     {        Iterator<String> it = list.iterator ();          while (It.hasnext ())         {            = it.next ();             if (S.equals ("B"))             {                it.remove ();}}    }

"Java" list passes the correct way to delete elements

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.