When learning collection in java, it is noted that the collection hierarchy root interface Collection implements the Iterable<T> interface (located in the java.lang package), which allows objects to become the target of the "foreach" statement. The only way in this interface is to return an iterator that iterates on a set of T-type elements.
1. Iterator
Interface: Iterator<T>
public interface Iterator<E>{ boolean hasNext(); E next(); void remove(); }Looking at the Iterator interface API, you can know that this is an iterator that iterates over the collection. The iterator allows the caller to remove elements from the collection pointed to by the iterator during iteration using well-defined semantics.
It is particularly noteworthy that this iterator remove() method is used: remove the last element returned by the iterator from the collection pointed to by the iterator (optional operation). This method can only be called once per call next. If the collection pointed to by the iterator is modified in other ways than calling this method (remove method) when iterating, the iterator's behavior is uncertain. When designing the Iterator<T> interface, the interface designer has pointed out that when iterating, if the remove() method except the iterator is called and the collection pointed to by the iterator is modified, it will cause uncertain consequences. What are the consequences depending on the specific implementation of the iterator. In response to the possible situations of this uncertain consequence, one of them was encountered when learning ArrayList: the iterator throws a ConcurrentModificationException exception. The specific exceptions are 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 } }} This code will throw a ConcurrentModificationException exception when running, because we do not use the iterator's remove() method to delete the element during the iterator's run, but instead use the ArrayList's remove() method to change the collection pointed to by the iterator. This violates the design principles of the iterator, so an exception occurs.
The reported abnormality is as follows:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Ittr.checkForComodification(ArrayList.java:859)
at java.util.ArrayList$Ittr.next(ArrayList.java:831)
at Text.ItaratorTest.main(ItaratorTest.java:17)
2. For-each loop and iterator Iterator<T>
Starting from Java 5, there is a for-each loop in Java, which can be used to loop through collection and array. Foreach loops allow you to traverse the collection without calling the hasNext() method in the while loop without keeping the index in the traditional for loop, or using iterator /ListIterator (an iterator implementation in ArrayList). The for-each loop simplifies the traversal process of any Collection or array. However, there are two points to pay attention to when using foreach loops.
Objects that use foreach loops must implement the Iterable<T> interface
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<T> interface, and the error reported during the compilation period 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)
In fact, there is no need to wait until the compilation to find an error. Eclipse will display an error in the foreach loop after the code is finished: 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 is only applicable to objects that implement the Iterable<T> interface. Since all built-in Collection classes implement the java.util.Collection interface and have inherited Iterable, in order to solve the above problem, you can choose to simply enable CustomCollection to 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(); } }}2. The internal implementation of the foreach loop is also implemented by Iterator.
To verify the fact that the foreach loop uses Iterator as an internal implementation, we still use the initial example of this article to verify:
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 runs:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Ittr.checkForComodification(ArrayList.java:859)
at java.util.ArrayList$Ittr.next(ArrayList.java:831)
at Text.ItaratorTest.main(ItaratorTest.java:22)
This exception just shows that the for-each loop uses Iterator to iterate through the Collection, which also calls Iterator.next(), which checks for (element) changes and throws a ConcurrentModificationException.
Summarize:
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.