Use of Iterator in Java collection

After seeing the iterator of the collection of Java core technology, write an article to record it

Interface iterator < E >, there are four methods: hasNext(), next(), remove(), forEachRemaining(), and the last method is jdk1 8 NEW

Next, use the method in the iterator to traverse a collection

1. In the traditional way, use hasNext(), next()

 public static void main(String[] args) {
        Collection<String> collection = new ArrayList<>();
        collection.add("111");
        collection.add("222");
        collection.add("333");
        collection.add("444");
        //Traversing a collection using iterators
        Iterator<String> iterator = collection.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
}

Source code of next():

private class Itr implements Iterator<E> {
        int cursor;// index of next element to return, the index of the next element to return, with an initial value of 0
        //Returns the index of the last element; If not, return - 1
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;

        // prevent creating a synthetic constructor
        Itr() {}

        public boolean hasNext() {
            return cursor != size;
        }

        @SuppressWarnings("unchecked")
        public E next() {
            checkForComodification();
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1;
            return (E) elementData[lastRet = i];
        }
}

After the first cycle: cursor becomes 1 and lastRet becomes 0

After the second cycle: cursor becomes 2 and lastRet becomes 1

After the third cycle: cursor becomes 3 and lastRet becomes 2

After the fourth cycle: cursor becomes 4 and lastRet becomes 3

Should Java An iterator is considered to be between two elements . When called next Time , The iterator passes over the next element and returns the reference of the element just crossed. This process is mainly controlled by the cursor variable.
 
If you want to delete the elements in the collection, you need to call next(), then remove(), and directly call remove(), which will report Java lang.IllegalStateException
        //Traversing a collection using iterators
        Iterator<String> iterator = collection.iterator();
        while (iterator.hasNext()){
            //System.out.println(iterator.next());
            iterator.remove();
            System.out.println(iterator.next());
        }

The correct way to write it is to restore the code commented out above

remove() source code

        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();
            }
        }

Each time, first judge whether the value of lastRet is less than 0. In next(), the value of lastRet will be modified to > = 0. Therefore, first call next(). After deletion, lastRet will become - 1 again. next() can only remove() once at a time

2.forEachRemaining(), perform the given operation on each remaining element until all elements are processed or the action throws an exception. Note that the remaining two words are very important. Look at an example

public static void main(String[] args) {
        Collection<String> collection = new ArrayList<>();
        collection.add("111");
        collection.add("222");
        collection.add("333");
        collection.add("444");
        //Traversing a collection using iterators
        Iterator<String> iterator = collection.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
        System.out.println("-------------------");
        //Use iterator's forEachRemaining
        iterator.forEachRemaining(item ->{
            System.out.println(item);
            //if ("333".equals(item))iterator.remove();
        });
}

The output is as follows:

111
222
333
444
-------------------

forEachRemaining does not traverse any elements, because the elements in the iterator have been traversed by the first method, and the iterator has no remaining elements. Take a look at the changes of parameters in the source code

Assign the value of cursor variable to variable i, i < size before traversing. Why is cursor equal to 4? It is because the value assigned by next() of while loop will not go through if judgment when calling the forEachRemaining method of iterator, so the rest is also controlled by cursor.

remove() cannot be called during forEachRemaining traversal, and Java. Com will be reported Lang. IllegalStateException, such as the following code

        Collection<String> collection = new ArrayList<>();
        collection.add("111");
        collection.add("222");
        collection.add("333");
        collection.add("444");
        //Traversing a collection using iterators
        Iterator<String> iterator = collection.iterator();
//        while (iterator.hasNext()){
//            System.out.println(iterator.next());
//        }
        System.out.println("-------------------");
        //Use iterator's forEachRemaining
        iterator.forEachRemaining(item ->{
            System.out.println(item);
            if ("333".equals(item))iterator.remove();
        });

From the above source code, we can see that next() is not used during the forEachRemaining traversal, and the for loop traversal is used, and the value of lastRet will not be modified until all traversals are completed. When remove() is called during the traversal, the lastRet at this time is still the initial value -1, and remove() has a judgment:

if (lastRet < 0)
   throw new IllegalStateException();

So throw an exception.

Tags: Java iterator

Posted by orbitalnets on Tue, 03 May 2022 00:45:04 +0300