Skip to content

Instantly share code, notes, and snippets.

@pyq
Created May 7, 2015 03:13

Revisions

  1. pyq created this gist May 7, 2015.
    112 changes: 112 additions & 0 deletions IteratorRemove.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,112 @@
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Collections;
    import java.util.Iterator;

    /**
    * Created by pyq on 5/6/15.
    */

    /*
    1. how does hasNext() work
    public boolean hasNext() {
    return cursor != size;
    }
    size: the number of elements it contains
    cursor: index of next element to return
    2. how does next() work
    public E next() {
    checkForComodification();
    ..
    returns the next element in the iteration
    }
    3. how does checkForComodification() work
    final void checkForComodification() {
    if (modCount != expectedModCount)
    throw new ConcurrentModificationException();
    }
    modCount: The number of times this list has been structurally modified.
    4. iterator.remove(); // increase modCount and also update expectedModCount, make it equal to modCount.
    5. collection.remove(value); // only increase modCount
    */


    public class IteratorRemove {
    public static void removeWithTwo() {
    Collection<String> collection = new ArrayList<String>(2);
    collection.add("one");
    collection.add("two");
    System.out.printf("%d%n", collection.size()); // 2
    for (String value : collection) {
    System.out.printf("%s%n", collection.remove(value)); // true
    }
    System.out.printf("%d%n", collection.size()); // 1
    }

    /*
    this for each loop just like following code
    for (Iterator<String> iterator = collection.iterator(); iterator.hasNext();) {
    String value = iterator.next();
    System.out.printf("%s%n", collection.remove(value));
    }
    after removed index 0 element(cursor 0), then increased the cursor by 1, now cursor is 1.
    (at the same time, size will decreased by 1, size is from 2 to 1)
    Because cursor == size. hasNext return false, (jump out of loop)
    We don't invoke next() after we removed the element "one", so we will not get ConcurrentModificationException
    and the collection.size() will just return size = 1.
    */

    public static void removeWithThree() {
    Collection<String> collection = new ArrayList<String>(2);
    collection.add("one");
    collection.add("two");
    collection.add("three");
    System.out.printf("%d%n", collection.size()); // 3
    for (String value : collection) {
    System.out.printf("%s%n", collection.remove(value)); // true then throws ConcurrentModificationException
    }
    System.out.printf("%d%n", collection.size());
    }
    // removeWithThree is just like removeWithThreeII
    /* with three element after we removed "one", cursor is 1, size is 2 (3 - 1), the hasNext will return true, (modCount++)
    now we jump to the next iteration of the loop(trying to remove "two"),
    but when invoke next(). we will throw ConcurrentModificationException (since modCount != expectedModCount) modeCount now is equal to expectedModCount + 1
    */
    public static void removeWithThreeII() {
    Collection<String> collection = new ArrayList<String>(2);
    collection.add("one");
    collection.add("two");
    collection.add("three");
    System.out.printf("%d%n", collection.size()); // 3
    for (Iterator<String> itr = collection.iterator(); itr.hasNext();) {
    String value = itr.next();
    System.out.printf("%s%n", collection.remove(value)); // true then throws ConcurrentModificationException
    }
    System.out.printf("%d%n", collection.size());
    }

    //Iterator.remove is the only safe way to modify a collection during iteration
    // when execute iterator.remove(); we will have modCount++ and expectedModCount = modCount. These two variables are always the same.
    public static void correctRemoveWithThree() {
    Collection<String> collection = new ArrayList<String>(2);
    collection.add("one");
    collection.add("two");
    collection.add("three");
    System.out.printf("%d%n", collection.size()); // 3
    Iterator<String> iterator = collection.iterator();
    while (iterator.hasNext()) {
    iterator.next();
    iterator.remove();
    }
    System.out.printf("%d%n", collection.size());
    }

    public static void main(String[] args) {
    //removeWithTwo();
    //removeWithThree();
    //removeWithThreeII();
    correctRemoveWithThree();
    }
    }