Home > 类库下载 > java类库 > for-each loop and iteration in JAVA

for-each loop and iteration in JAVA

高洛峰
Release: 2016-10-19 09:59:15
Original
1862 people have browsed it

1. Iterator Iterator

Interface: Iterator

public interface Iterator<E>{

 boolean hasNext();

 E next();

 void remove();
 }
Copy after login

Looking at the Iterator interface API, you can know that this is an iterator for iterating the collection. Iterators allow the caller to remove elements from the collection pointed to by the iterator during iteration using well-defined semantics.

Particularly noteworthy is the use of the remove() method of this iterator: remove the last element returned by the iterator (optional operation) from the collection pointed to by the iterator. This method can only be called once per call to next. If the collection pointed to by the iterator is modified during an iteration other than by calling this method (remove method), the behavior of the iterator is undefined. The interface designer pointed out when designing the Iterator interface that if the remove() method other than the iterator is called to modify the collection pointed by the iterator during iteration, it will cause uncertain consequences. The specific consequences depend on the specific implementation of the iterator. In response to the possible situations where such uncertain consequences may occur, I encountered one of them when learning ArrayList: the iterator threw a ConcurrentModificationException exception. The specific exception is shown in the following code:

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class ItaratorTest {

    public static void main(String[] args) {
        Collection<String> list = new ArrayList<String>();
        list.add("Android");
        list.add("IOS");
        list.add("Windows Mobile");

        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            String lang = iterator.next();
            list.remove(lang);//will throw ConcurrentModificationException
        }
    }

}
Copy after login

This code will throw a ConcurrentModificationException exception during runtime, because we do not use the iterator's remove() method to delete elements during the iterator's operation, but use ArrayList's remove() Method changes the collection pointed by the iterator. This violates the design principles of iterators, so an exception occurs.
The reported exception is as follows:

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
    at java.util.ArrayList$Itr.next(ArrayList.java:831)
    at Text.ItaratorTest.main(ItaratorTest.java:17)
Copy after login

2. for-each loop and iterator Iterator

Starting from Java5, there is a for-each loop in Java, which can be used to loop through collections and arrays. The Foreach loop allows you to iterate through the collection without maintaining the index in a traditional for loop, or without calling the hasNext() method in the while loop when using iterator / ListIterator (an iterator implementation in ArrayList). The for-each loop simplifies the process of traversing any Collection or array. But there are two points to note when using a foreach loop.

Objects using the foreach loop must implement the Iterableinterface

Please see the following example:

import java.util.ArrayList;

public class ForeachTest1 {

    public static void main(String args[]) {
        CustomCollection<String> myCollection = new CustomCollection<String>();
        myCollection.add("Java");
        myCollection.add("Scala");
        myCollection.add("Groovy");

        // What does this code will do, print language, throw exception or
        // compile time error
        for (String language : myCollection) {
            System.out.println(language);
        }
    }

    private class CustomCollection<T> {
        private ArrayList<T> bucket;

        public CustomCollection() {
            bucket = new ArrayList();
        }

        public int size() {
            return bucket.size();
        }

        public boolean isEmpty() {
            return bucket.isEmpty();
        }

        public boolean contains(T o) {
            return bucket.contains(o);
        }

        public boolean add(T e) {
            return bucket.add(e);
        }

        public boolean remove(T o) {
            return bucket.remove(o);
        }

    }
}
Copy after login

The above code will not be compiled. This is because the CustomCollection class in the code does not implement the Iterableinterface. The error reported during compilation is as follows :

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
    Can only iterate over an array or an instance of java.lang.Iterable

    at Text.ForeachTest1.main(ForeachTest1.java:15)
Copy after login

In fact, there is no need to wait until compilation to find the error. Eclipse will display the error in the foreach loop after writing this code: Can only iterate over an array or an instance of java.lang.Iterable

What can be confirmed again from the above example is that the foreach loop only applies to objects that implement the Iterable interface. Since all built-in Collection classes implement the java.util.Collection interface and have inherited Iterable, in order to solve the above problems, you can choose to simply let CustomCollection implement the Collection interface or inherit AbstractCollection. The solution is as follows:

import java.util.AbstractCollection;
import java.util.ArrayList;
import java.util.Iterator;

public class ForeachTest {
    public static void main(String args[]) {
        CustomCollection<String> myCollection = new CustomCollection<String>();
        myCollection.add("Java");
        myCollection.add("Scala");
        myCollection.add("Groovy");
        for (String language : myCollection) {
            System.out.println(language);
        }
    }

    private static class CustomCollection<T> extends AbstractCollection<T> {
        private ArrayList<T> bucket;

        public CustomCollection() {
            bucket = new ArrayList();
        }

        public int size() {
            return bucket.size();
        }

        public boolean isEmpty() {
            return bucket.isEmpty();
        }

        public boolean contains(Object o) {
            return bucket.contains(o);
        }

        public boolean add(T e) {
            return bucket.add(e);
        }

        public boolean remove(Object o) {
            return bucket.remove(o);
        }

        @Override
        public Iterator<T> iterator() {
            // TODO Auto-generated method stub
            return bucket.iterator();
        }
    }
}
Copy after login

  2. The internal implementation of the foreach loop also relies on Iterator

In order to verify the fact that the foreach loop uses Iterator as the internal implementation, we still use the initial example of this article for verification:

public class ItaratorTest {

    public static void main(String[] args) {
        Collection<String> list = new ArrayList<String>();
        list.add("Android");
        list.add("IOS");
        list.add("Windows Mobile");

        // example1
        // Iterator<String> iterator = list.iterator();
        // while (iterator.hasNext()) {
        // String lang = iterator.next();
        // list.remove(lang);
        // }

        // example 2
        for (String language : list) {
            list.remove(language);
        }
    }

}
Copy after login

Exception reported when the program is running:

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
    at java.util.ArrayList$Itr.next(ArrayList.java:831)
    at Text.ItaratorTest.main(ItaratorTest.java:22)
Copy after login

This exception shows that an Iterator is used inside the for-each loop to traverse the Collection. It also calls Iterator.next(), which checks the changes (of elements) and throws a ConcurrentModificationException.

Summary:

When traversing a collection, if you want to modify the collection during the traversal, you must do it through Iterator/listIterator, otherwise "undetermined consequences" may occur.

The foreach loop is implemented through iterator, and the object using the foreach loop must implement the Iterable interface


Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template