When learning collection in java, I noticed that the root interface Collection of the collection level implements the Iterable
1. IteratorIterator
Interface: Iterator
public interface Iterator<E>{ boolean hasNext(); E next(); void remove(); }
Looking at the Iterator interface API, you can know that this is a reference to collection An iterator to iterate over. Iterators allow the caller to remove elements from the collection pointed to by the iterator during iteration using well-defined semantics.
Of particular note 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
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 } } }
This code will throw a ConcurrentModificationException exception when running, because we did not use the iterator during the iterator operation remove() method to remove elements, but use the ArrayList's remove() method to change 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)
2. for-each loop and iterator Iterator
Since 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 over 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 foreach loop must implement the Iterable
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); } } }
The above code will not be compiled because the CustomCollection class in the code does not implement the Iterable
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)
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
It can be confirmed again from the above example that the foreach loop only applies to objects that implement the Iterable
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(); } } }
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 example at the beginning 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); } } }
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)
This exception shows that the Iterator is used inside the for-each loop to traverse the Collection. It also calls Iterator.next(), which checks (the element) changes and throws ConcurrentModificationException.
Summary:
When traversing a collection, if you want to modify the collection during the traversal, you must do it through Iterator/listIterator, otherwise "uncertain consequences" may occur.
The foreach loop is implemented through iterator, and the object using the foreach loop must implement the Iterable interface
The above is the entire content of this article. I hope it will be helpful to everyone's study. I also hope that everyone will support the PHP Chinese website.
For more detailed articles related to for-each loop and iteration in JAVA, please pay attention to the PHP Chinese website!